home *** CD-ROM | disk | FTP | other *** search
/ Amiga Games Extra 1996 September / Amiga Games Extra CD-ROM 9-1996.iso / userbox / publicdomain / vim-4.2 / src / memline.c < prev    next >
C/C++ Source or Header  |  1996-06-12  |  89KB  |  3,383 lines

  1. /* vi:set ts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8.  
  9. /* for debugging */
  10. /* #define CHECK(c, s)    if (c) EMSG(s) */
  11. #define CHECK(c, s)
  12.  
  13. /*
  14.  * memline.c: Contains the functions for appending, deleting and changing the
  15.  * text lines. The memfile functions are used to store the information in blocks
  16.  * of memory, backed up by a file. The structure of the information is a tree.
  17.  * The root of the tree is a pointer block. The leaves of the tree are data
  18.  * blocks. In between may be several layers of pointer blocks, forming branches.
  19.  *
  20.  * Three types of blocks are used:
  21.  * - Block nr 0 contains information for recovery
  22.  * - Pointer blocks contain list of pointers to other blocks.
  23.  * - Data blocks contain the actual text.
  24.  *
  25.  * Block nr 0 contains the block0 structure (see below).
  26.  *
  27.  * Block nr 1 is the first pointer block. It is the root of the tree.
  28.  * Other pointer blocks are branches.
  29.  *
  30.  *    If a line is too big to fit in a single page, the block
  31.  *    containing that line is made big enough to hold the line. It may span
  32.  *      several pages. Otherwise all blocks are one page.
  33.  *
  34.  *    A data block that was filled when starting to edit a file and was not
  35.  *      changed since then, can have a negative block number. This means that it
  36.  *      has not yet been assigned a place in the file. When recovering, the lines
  37.  *       in this data block can be read from the original file. When the block is
  38.  *    changed (lines appended/deleted/changed) or when it is flushed it gets
  39.  *    a positive number. Use mf_trans_del() to get the new number, before
  40.  *    calling mf_get().
  41.  */
  42.  
  43. /*
  44.  * The following functions are available to work with a memline:
  45.  * 
  46.  * ml_open()            open a new memline for a buffer
  47.  * ml_setname()            change the file name for a memline
  48.  * ml_close()            close the memline for a buffer
  49.  * ml_close_all()        close all memlines
  50.  * ml_recover()            read a memline for recovery
  51.  * ml_sync_all()        flush changed blocks to file for all files
  52.  * ml_preserve()        flush everything into the file for one file
  53.  * ml_get()                get a pointer to a line
  54.  * ml_get_pos()            get a pointer to a position in a line
  55.  * ml_get_cursor()        get a pointer to the char under the cursor
  56.  * ml_get_buf()            get a pointer to a line in a specific buffer
  57.  * ml_line_alloced()    return TRUE if line was allocated
  58.  * ml_append()            append a new line
  59.  * ml_replace()            replace a line
  60.  * ml_delete()            delete a line
  61.  * ml_setmarked()        set mark for a line (for :global command)
  62.  * ml_firstmarked()        get first line with a mark (for :global command)
  63.  * ml_clearmarked()        clear all line marks (for :global command)
  64.  */
  65.  
  66. #if defined MSDOS  ||  defined WIN32
  67. # include <io.h>
  68. #endif
  69.  
  70. #include "vim.h"
  71. #include "globals.h"
  72. #include "proto.h"
  73. #include "option.h"
  74. #ifdef HAVE_FCNTL_H
  75. # include <fcntl.h>
  76. #endif
  77. #ifndef UNIX            /* it's in unix.h for Unix */
  78. # include <time.h>
  79. #endif
  80.  
  81. #ifdef SASC
  82. # include <proto/dos.h>        /* for Open() and Close() */
  83. #endif
  84.  
  85. typedef struct block0            ZERO_BL;    /* contents of the first block */
  86. typedef struct pointer_block    PTR_BL;        /* contents of a pointer block */
  87. typedef struct data_block        DATA_BL;    /* contents of a data block */
  88. typedef struct pointer_entry    PTR_EN;        /* block/line-count pair */
  89.  
  90. #define DATA_ID        (('d' << 8) + 'a')        /* data block id */
  91. #define PTR_ID        (('p' << 8) + 't')        /* pointer block id */
  92. #define BLOCK0_ID0    'b'                        /* block 0 id 0 */
  93. #define BLOCK0_ID1    '0'                        /* block 0 id 1 */
  94.  
  95. /*
  96.  * pointer to a block, used in a pointer block
  97.  */
  98. struct pointer_entry
  99. {
  100.     blocknr_t    pe_bnum;        /* block number */
  101.     linenr_t    pe_line_count;    /* number of lines in this branch */
  102.     linenr_t    pe_old_lnum;    /* lnum for this block (for recovery) */
  103.     int            pe_page_count;    /* number of pages in block pe_bnum */
  104. };
  105.  
  106. /*
  107.  * A pointer block contains a list of branches in the tree.
  108.  */
  109. struct pointer_block
  110. {
  111.     short_u        pb_id;            /* ID for pointer block: PTR_ID */
  112.     short_u        pb_count;        /* number of pointer in this block */
  113.     short_u        pb_count_max;    /* maximum value for pb_count */
  114.     PTR_EN        pb_pointer[1];    /* list of pointers to blocks (actually longer)
  115.                                  * followed by empty space until end of page */
  116. };
  117.  
  118. /*
  119.  * A data block is a leaf in the tree.
  120.  *
  121.  * The text of the lines is at the end of the block. The text of the first line
  122.  * in the block is put at the end, the text of the second line in front of it,
  123.  * etc. Thus the order of the lines is the opposite of the line number.
  124.  */
  125. struct data_block
  126. {
  127.     short_u        db_id;            /* ID for data block: DATA_ID */
  128.     unsigned    db_free;        /* free space available */
  129.     unsigned    db_txt_start;    /* byte where text starts */
  130.     unsigned    db_txt_end;        /* byte just after data block */
  131.     linenr_t    db_line_count;    /* number of lines in this block */
  132.     unsigned    db_index[1];    /* index for start of line (actually bigger)
  133.                                  * followed by empty space upto db_txt_start
  134.                                  * followed by the text in the lines until
  135.                                  * end of page */
  136. };
  137.  
  138. /*
  139.  * The low bits of db_index hold the actual index. The topmost bit is
  140.  * used for the global command to be able to mark a line. 
  141.  * This method is not clean, but otherwise there would be at least one extra
  142.  * byte used for each line.
  143.  * The mark has to be in this place to keep it with the correct line when other
  144.  * lines are inserted or deleted.
  145.  */
  146. #define DB_MARKED        ((unsigned)1 << ((sizeof(unsigned) * 8) - 1))
  147. #define DB_INDEX_MASK    (~DB_MARKED)
  148.  
  149. #define INDEX_SIZE    (sizeof(unsigned))        /* size of one db_index entry */
  150. #define HEADER_SIZE    (sizeof(DATA_BL) - INDEX_SIZE)    /* size of data block header */
  151.  
  152. #define B0_FNAME_SIZE    900
  153. #define B0_UNAME_SIZE    40
  154. #define B0_HNAME_SIZE    40
  155. /*
  156.  * Restrict the numbers to 32 bits, otherwise most compilers will complain.
  157.  * This won't detect a 64 bit machine that only swaps a byte in the top 32
  158.  * bits, but that is crazy anyway.
  159.  */
  160. #define B0_MAGIC_LONG    0x30313233
  161. #define B0_MAGIC_INT    0x20212223
  162. #define B0_MAGIC_SHORT    0x10111213
  163. #define B0_MAGIC_CHAR    0x55
  164.  
  165. /*
  166.  * Block zero holds all info about the swap file.
  167.  *
  168.  * NOTE: DEFINITION OF BLOCK 0 SHOULD NOT CHANGE, it makes all existing swap
  169.  * files unusable!
  170.  * 
  171.  * If size of block0 changes anyway, adjust minimal block size
  172.  * in mf_open()!!
  173.  *
  174.  * This block is built up of single bytes, to make it portable accros
  175.  * different machines. b0_magic_* is used to check the byte order and size of
  176.  * variables, because the rest of the swap is not portable.
  177.  */
  178. struct block0
  179. {
  180.     char_u        b0_id[2];        /* id for block 0: BLOCK0_ID0 and BLOCK0_ID1 */
  181.     char_u        b0_version[10];    /* Vim version string */
  182.     char_u        b0_page_size[4];/* number of bytes per page */
  183.     char_u        b0_mtime[4];    /* last modification time of file */
  184.     char_u        b0_ino[4];        /* inode of b0_fname */
  185.     char_u        b0_pid[4];        /* process id of creator (or 0) */
  186.     char_u        b0_uname[B0_UNAME_SIZE]; /* name of user (uid if no name) */
  187.     char_u        b0_hname[B0_HNAME_SIZE]; /* host name (if it has a name) */
  188.     char_u        b0_fname[B0_FNAME_SIZE]; /* name of file being edited */
  189.     long        b0_magic_long;    /* check for byte order of long */
  190.     int            b0_magic_int;    /* check for byte order of int */
  191.     short        b0_magic_short;    /* check for byte order of short */
  192.     char_u        b0_magic_char;    /* check for last char */
  193. };
  194.  
  195. #define STACK_INCR        5        /* nr of entries added to ml_stack at a time */
  196.  
  197. /*
  198.  * The line number where the first mark may be is remembered.
  199.  * If it is 0 there are no marks at all.
  200.  * (always used for the current buffer only, no buffer change possible while
  201.  * executing a global command).
  202.  */
  203. static linenr_t    lowest_marked = 0;
  204.  
  205. /*
  206.  * arguments for ml_find_line()
  207.  */
  208. #define ML_DELETE        0x11        /* delete line */
  209. #define ML_INSERT        0x12        /* insert line */
  210. #define ML_FIND            0x13        /* just find the line */
  211. #define ML_FLUSH        0x02        /* flush locked block */
  212. #define ML_SIMPLE(x)    (x & 0x10)    /* DEL, INS or FIND */
  213.  
  214. static void ml_open_file __ARGS((BUF *));
  215. static void set_b0_fname __ARGS((ZERO_BL *, BUF *buf));
  216. static void swapfile_info __ARGS((char_u *));
  217. static int get_names __ARGS((char_u **, char_u *));
  218. static int ml_append_int __ARGS((BUF *, linenr_t, char_u *, colnr_t, int));
  219. static int ml_delete_int __ARGS((BUF *, linenr_t, int));
  220. static char_u *findswapname __ARGS((BUF *, char_u **, char_u *));
  221. static void ml_flush_line __ARGS((BUF *));
  222. static BHDR *ml_new_data __ARGS((MEMFILE *, int, int));
  223. static BHDR *ml_new_ptr __ARGS((MEMFILE *));
  224. static BHDR *ml_find_line __ARGS((BUF *, linenr_t, int));
  225. static int ml_add_stack __ARGS((BUF *));
  226. static char_u *makeswapname __ARGS((BUF *, char_u *));
  227. static void ml_lineadd __ARGS((BUF *, int));
  228. static int b0_magic_wrong __ARGS((ZERO_BL *));
  229. #ifdef CHECK_INODE
  230. static int fnamecmp_ino __ARGS((char_u *, char_u *, long));
  231. #endif
  232. static void long_to_char __ARGS((long, char_u *));
  233. static long char_to_long __ARGS((char_u *));
  234.  
  235. /*
  236.  * open a new memline for 'curbuf'
  237.  *
  238.  * return FAIL for failure, OK otherwise
  239.  */
  240.     int
  241. ml_open()
  242. {
  243.     MEMFILE        *mfp;
  244.     char_u        *fname;
  245.     BHDR        *hp = NULL;
  246.     ZERO_BL        *b0p;
  247.     PTR_BL        *pp;
  248.     DATA_BL        *dp;
  249.     char_u        *dirp;
  250.  
  251. /*
  252.  * init fields in memline struct
  253.  */
  254.     curbuf->b_ml.ml_stack_size = 0;        /* no stack yet */
  255.     curbuf->b_ml.ml_stack = NULL;        /* no stack yet */
  256.     curbuf->b_ml.ml_stack_top = 0;        /* nothing in the stack */
  257.     curbuf->b_ml.ml_locked = NULL;        /* no cached block */
  258.     curbuf->b_ml.ml_line_lnum = 0;        /* no cached line */
  259.  
  260. /*
  261.  * Make file name for swap file.
  262.  * If we are unable to find a file name, mf_fname will be NULL
  263.  * and the memfile will be in memory only (no recovery possible).
  264.  * When 'updatecount' is 0 and for help files on Unix there is never a swap
  265.  * file.
  266.  */
  267. #if defined(UNIX) || defined(__EMX__)
  268. /* why only on Unix an exception for help files??? */
  269.     if (p_uc == 0 || curbuf->b_help)
  270. #else
  271.     if (p_uc == 0)
  272. #endif
  273.         dirp = (char_u *)"";
  274.     else
  275.         dirp = p_dir;
  276.     
  277. /*
  278.  * Open the memfile.
  279.  *
  280.  * If no swap file is wanted *dirp will be NUL, try with fname == NULL.
  281.  * Otherwise try all directories in 'directory' option. If that fails try
  282.  * with fname == NULL.
  283.  */
  284.     for (;;)
  285.     {
  286.         if (*dirp == NUL)
  287.             fname = NULL;
  288.         else
  289.         {
  290.             fname = findswapname(curbuf, &dirp, NULL);
  291.             if (fname == NULL)
  292.                 continue;
  293.         }
  294.         mfp = mf_open(fname, TRUE);
  295.         /* stop when memfile opened or no other fname to try */
  296.         if (mfp != NULL || (fname == NULL && *dirp == NUL))
  297.             break;
  298.         vim_free(fname);
  299.     }
  300.  
  301.     if (mfp == NULL)
  302.         goto error;
  303.     curbuf->b_ml.ml_mfp = mfp;
  304.     curbuf->b_ml.ml_flags = ML_EMPTY;
  305.     curbuf->b_ml.ml_line_count = 1;
  306.  
  307.     if (!(p_uc == 0 || curbuf->b_help) && mfp->mf_fname == NULL)
  308.     {
  309.         need_wait_return = TRUE;        /* call wait_return later */
  310.         ++no_wait_return;
  311.         (void)EMSG("Unable to open swap file, recovery impossible");
  312.         --no_wait_return;
  313.     }
  314. #if defined(MSDOS) || defined(WIN32)
  315.     /*
  316.      * set full pathname for swap file now, because a ":!cd dir" may
  317.      * change directory without us knowing it.
  318.      */
  319.     mf_fullname(mfp);
  320. #endif
  321.  
  322. /*
  323.  * fill block0 struct and write page 0
  324.  */
  325.     if ((hp = mf_new(mfp, FALSE, 1)) == NULL)
  326.         goto error;
  327.     if (hp->bh_bnum != 0)
  328.     {
  329.         EMSG("didn't get block nr 0?");
  330.         goto error;
  331.     }
  332.     b0p = (ZERO_BL *)(hp->bh_data);
  333.  
  334.     (void)vim_memset(b0p, 0, sizeof(ZERO_BL));        /* init all to zero */
  335.  
  336.     b0p->b0_id[0] = BLOCK0_ID0;
  337.     b0p->b0_id[1] = BLOCK0_ID1;
  338.     b0p->b0_magic_long = (long)B0_MAGIC_LONG;
  339.     b0p->b0_magic_int = (int)B0_MAGIC_INT;
  340.     b0p->b0_magic_short = (short)B0_MAGIC_SHORT;
  341.     b0p->b0_magic_char = B0_MAGIC_CHAR;
  342.  
  343.     STRNCPY(b0p->b0_version, Version, 10);
  344.     set_b0_fname(b0p, curbuf);
  345.     long_to_char((long)mfp->mf_page_size, b0p->b0_page_size);
  346.     (void)mch_get_user_name(b0p->b0_uname, B0_UNAME_SIZE);
  347.     b0p->b0_uname[B0_UNAME_SIZE - 1] = NUL;
  348.     mch_get_host_name(b0p->b0_hname, B0_HNAME_SIZE);
  349.     b0p->b0_hname[B0_HNAME_SIZE - 1] = NUL;
  350.     long_to_char(mch_get_pid(), b0p->b0_pid);
  351.  
  352.     /*
  353.      * Always sync block number 0 to disk, so we can check the file name in
  354.      * the swap file in findswapname(). Don't do this for help files though.
  355.      */
  356.     mf_put(mfp, hp, TRUE, FALSE);
  357.     if (!curbuf->b_help)
  358.         mf_sync(mfp, FALSE, FALSE, FALSE);
  359.  
  360. /*
  361.  * fill in root pointer block and write page 1
  362.  */
  363.     if ((hp = ml_new_ptr(mfp)) == NULL)
  364.         goto error;
  365.     if (hp->bh_bnum != 1)
  366.     {
  367.         EMSG("didn't get block nr 1?");
  368.         goto error;
  369.     }
  370.     pp = (PTR_BL *)(hp->bh_data);
  371.     pp->pb_count = 1;
  372.     pp->pb_pointer[0].pe_bnum = 2;
  373.     pp->pb_pointer[0].pe_page_count = 1;
  374.     pp->pb_pointer[0].pe_old_lnum = 1;
  375.     pp->pb_pointer[0].pe_line_count = 1;    /* line count after insertion */
  376.     mf_put(mfp, hp, TRUE, FALSE);
  377.  
  378. /*
  379.  * allocate first data block and create an empty line 1.
  380.  */
  381.     if ((hp = ml_new_data(mfp, FALSE, 1)) == NULL)
  382.         goto error;
  383.     if (hp->bh_bnum != 2)
  384.     {
  385.         EMSG("didn't get block nr 2?");
  386.         goto error;
  387.     }
  388.  
  389.     dp = (DATA_BL *)(hp->bh_data);
  390.     dp->db_index[0] = --dp->db_txt_start;        /* at end of block */
  391.     dp->db_free -= 1 + INDEX_SIZE;
  392.     dp->db_line_count = 1;
  393.     *((char_u *)dp + dp->db_txt_start) = NUL;    /* emtpy line */
  394.  
  395.     return OK;
  396.  
  397. error:
  398.     if (mfp != NULL)
  399.     {
  400.         if (hp)
  401.             mf_put(mfp, hp, FALSE, FALSE);
  402.         mf_close(mfp, TRUE);        /* will also free(mfp->mf_fname) */
  403.     }
  404.     else
  405.         vim_free(fname);
  406.     curbuf->b_ml.ml_mfp = NULL;
  407.     return FAIL;
  408. }
  409.  
  410. /*
  411.  * ml_setname() is called when the file name has been changed.
  412.  * It may rename the swap file.
  413.  */
  414.     void
  415. ml_setname()
  416. {
  417.     int            success = FALSE;
  418.     MEMFILE        *mfp;
  419.     char_u        *fname;
  420.     char_u        *dirp;
  421.  
  422. /*
  423.  * When 'updatecount' is 0 there is never a swap file.
  424.  * For help files we will make a swap file now.
  425.  */
  426.     if (p_uc == 0)
  427.         return;
  428.  
  429.     mfp = curbuf->b_ml.ml_mfp;
  430.     if (mfp->mf_fd < 0)                /* there is no swap file yet */
  431.     {
  432.         ml_open_file(curbuf);        /* create a swap file */
  433.         return;
  434.     }
  435.  
  436. /*
  437.  * Try all directories in the 'directory' option.
  438.  */
  439.     dirp = p_dir;
  440.     for (;;)
  441.     {
  442.         if (*dirp == NUL)            /* tried all directories, fail */
  443.             break;
  444.         fname = findswapname(curbuf, &dirp, mfp->mf_fname);
  445.         if (fname == NULL)            /* no file name found for this dir */
  446.             continue;
  447.  
  448. #if defined(MSDOS) || defined(WIN32)
  449.         /*
  450.          * Set full pathname for swap file now, because a ":!cd dir" may
  451.          * change directory without us knowing it.
  452.          */
  453.         if (!did_cd)
  454.         {
  455.             char_u        *p;
  456.  
  457.             p = FullName_save(fname);
  458.             vim_free(fname);
  459.             fname = p;
  460.             if (fname == NULL)
  461.                 continue;
  462.         }
  463. #endif
  464.             /* if the file name is the same we don't have to do anything */
  465.         if (fnamecmp(fname, mfp->mf_fname) == 0)
  466.         {
  467.             vim_free(fname);
  468.             success = TRUE;
  469.             break;
  470.         }
  471.             /* need to close the swap file before renaming */
  472.         if (mfp->mf_fd >= 0)
  473.         {
  474.             close(mfp->mf_fd);
  475.             mfp->mf_fd = -1;
  476.         }
  477.  
  478.             /* try to rename the swap file */
  479.         if (vim_rename(mfp->mf_fname, fname) == 0)
  480.         {
  481.             success = TRUE;
  482.             vim_free(mfp->mf_fname);
  483.             mfp->mf_fname = fname;
  484.             vim_free(mfp->mf_xfname);
  485.             mf_set_xfname(mfp);
  486.             break;
  487.         }
  488.         vim_free(fname);            /* this fname didn't work, try another */
  489.     }
  490.  
  491.     if (mfp->mf_fd == -1)            /* need to (re)open the swap file */
  492.     {
  493.         mfp->mf_fd = open((char *)mfp->mf_fname, O_RDWR | O_EXTRA);
  494.         if (mfp->mf_fd < 0)
  495.         {
  496.             /* could not (re)open the swap file, what can we do???? */
  497.             EMSG("Oops, lost the swap file!!!");
  498.             return;
  499.         }
  500.     }
  501.     if (!success)
  502.         EMSG("Could not rename swap file");
  503. }
  504.  
  505. /*
  506.  * Open a file for the memfile for all buffers.
  507.  * Used when 'updatecount' changes from zero to non-zero.
  508.  */
  509.     void
  510. ml_open_files()
  511. {
  512.     BUF            *buf;
  513.  
  514.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  515.         ml_open_file(buf);
  516. }
  517.  
  518. /*
  519.  * Open a swap file for an existing memfile, if there is non swap file yet.
  520.  */
  521.     static void
  522. ml_open_file(buf)
  523.     BUF            *buf;
  524. {
  525.     MEMFILE        *mfp;
  526.     char_u        *fname;
  527.     char_u        *dirp;
  528.  
  529.     mfp = buf->b_ml.ml_mfp;
  530.     if (mfp == NULL || mfp->mf_fd >= 0)            /* nothing to do */
  531.         return;
  532.  
  533.     dirp = p_dir;
  534. /*
  535.  * Try all directories in 'directory' option.
  536.  */
  537.     for (;;)
  538.     {
  539.         if (*dirp == NUL)
  540.             break;
  541.         fname = findswapname(buf, &dirp, NULL);
  542.         if (fname == NULL)
  543.             continue;
  544.         if (mf_open_file(mfp, fname) == OK)
  545.             break;
  546.         vim_free(fname);
  547.     }
  548.  
  549.     if (mfp->mf_fname == NULL)            /* Failed! */
  550.     {
  551.         need_wait_return = TRUE;        /* call wait_return later */
  552.         ++no_wait_return;
  553.         (void)EMSG2("Unable to open swap file for \"%s\", recovery impossible",
  554.                 buf->b_xfilename == NULL ? (char_u *)"No File"
  555.                                          : buf->b_xfilename);
  556.         --no_wait_return;
  557.     }
  558. #if defined(MSDOS) || defined(WIN32)
  559.     /*
  560.      * set full pathname for swap file now, because a ":!cd dir" may
  561.      * change directory without us knowing it.
  562.      */
  563.     else
  564.         mf_fullname(mfp);
  565. #endif
  566. }
  567.  
  568. /*
  569.  * Close memline for buffer 'buf'.
  570.  * If 'del_file' is TRUE, delete the swap file
  571.  */
  572.     void
  573. ml_close(buf, del_file)
  574.     BUF        *buf;
  575.     int        del_file;
  576. {
  577.     if (buf->b_ml.ml_mfp == NULL)                /* not open */
  578.         return;
  579.     mf_close(buf->b_ml.ml_mfp, del_file);            /* close the .swp file */
  580.     if (buf->b_ml.ml_line_lnum != 0 && (buf->b_ml.ml_flags & ML_LINE_DIRTY))
  581.         vim_free(buf->b_ml.ml_line_ptr);
  582.     vim_free(buf->b_ml.ml_stack);
  583.     buf->b_ml.ml_mfp = NULL;
  584. }
  585.  
  586. /*
  587.  * Close all existing memlines and memfiles.
  588.  * Used when exiting.
  589.  * When 'del_file' is TRUE, delete the memfiles.
  590.  */
  591.     void
  592. ml_close_all(del_file)
  593.     int        del_file;
  594. {
  595.     BUF        *buf;
  596.  
  597.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  598.         ml_close(buf, del_file);
  599. }
  600.  
  601. /*
  602.  * Close all memfiles for not modified buffers.
  603.  * Only use just before exiting!
  604.  */
  605.     void
  606. ml_close_notmod()
  607. {
  608.     BUF        *buf;
  609.  
  610.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  611.         if (!buf->b_changed)
  612.             ml_close(buf, TRUE);    /* close all not-modified buffers */
  613. }
  614.  
  615. /*
  616.  * Update the timestamp in the .swp file.
  617.  * Used when the file has been written.
  618.  */
  619.     void
  620. ml_timestamp(buf)
  621.     BUF            *buf;
  622. {
  623.     MEMFILE        *mfp;
  624.     BHDR        *hp;
  625.     ZERO_BL        *b0p;
  626.  
  627.     mfp = buf->b_ml.ml_mfp;
  628.  
  629.     if (mfp == NULL || (hp = mf_get(mfp, (blocknr_t)0, 1)) == NULL)
  630.         return;
  631.     b0p = (ZERO_BL *)(hp->bh_data);
  632.     if (b0p->b0_id[0] != BLOCK0_ID0 || b0p->b0_id[1] != BLOCK0_ID1)
  633.         EMSG("ml_timestamp: Didn't get block 0??");
  634.     else
  635.         set_b0_fname(b0p, buf);
  636.     mf_put(mfp, hp, TRUE, FALSE);
  637. }
  638.  
  639. /*
  640.  * Write file name and timestamp into block 0 of a swap file.
  641.  * Also set buf->b_mtime.
  642.  * Don't use NameBuff[]!!!
  643.  */
  644.     static void
  645. set_b0_fname(b0p, buf)
  646.     ZERO_BL        *b0p;
  647.     BUF            *buf;
  648. {
  649.     struct stat    st;
  650.     size_t        flen, ulen;
  651.     char_u        uname[B0_UNAME_SIZE];
  652.  
  653.     if (buf->b_filename == NULL)
  654.         b0p->b0_fname[0] = NUL;
  655.     else
  656.     {
  657.         /*
  658.          * For a file under the home directory of the current user, we try to
  659.          * replace the home directory path with "~user". This helps when
  660.          * editing the same file on different machines over a network.
  661.          * First replace home dir path with "~/" with home_replace().
  662.          * Then insert the user name to get "~user/".
  663.          */
  664.         home_replace(NULL, buf->b_filename, b0p->b0_fname, B0_FNAME_SIZE);
  665.         if (b0p->b0_fname[0] == '~')
  666.         {
  667.             flen = STRLEN(b0p->b0_fname);
  668.             /* If there is no user name or it is too long, don't use "~/" */
  669.             if (mch_get_user_name(uname, B0_UNAME_SIZE) == FAIL ||
  670.                          (ulen = STRLEN(uname)) + flen > B0_FNAME_SIZE - 1)
  671.                 STRNCPY(b0p->b0_fname, buf->b_filename, B0_FNAME_SIZE);
  672.             else
  673.             {
  674.                 vim_memmove(b0p->b0_fname + ulen + 1, b0p->b0_fname + 1, flen);
  675.                 vim_memmove(b0p->b0_fname + 1, uname, ulen);
  676.             }
  677.         }
  678.         if (stat((char *)buf->b_filename, &st) >= 0)
  679.         {
  680.             long_to_char((long)st.st_mtime, b0p->b0_mtime);
  681. #ifdef CHECK_INODE
  682.             long_to_char((long)st.st_ino, b0p->b0_ino);
  683. #endif
  684.             buf->b_mtime = st.st_mtime;
  685.             buf->b_mtime_read = st.st_mtime;
  686.         }
  687.         else
  688.         {
  689.             long_to_char(0L, b0p->b0_mtime);
  690. #ifdef CHECK_INODE
  691.             long_to_char(0L, b0p->b0_ino);
  692. #endif
  693.             buf->b_mtime = 0;
  694.             buf->b_mtime_read = 0;
  695.         }
  696.     }
  697. }
  698.  
  699. /*
  700.  * try to recover curbuf from the .swp file
  701.  */
  702.     void
  703. ml_recover()
  704. {
  705.     BUF            *buf = NULL;
  706.     MEMFILE        *mfp = NULL;
  707.     char_u        *fname;
  708.     BHDR        *hp = NULL;
  709.     ZERO_BL        *b0p;
  710.     PTR_BL        *pp;
  711.     DATA_BL        *dp;
  712.     IPTR        *ip;
  713.     blocknr_t    bnum;
  714.     int            page_count;
  715.     struct stat    org_stat, swp_stat;
  716.     int            len;
  717.     int            directly;
  718.     linenr_t    lnum;
  719.     char_u        *p;
  720.     int            i;
  721.     long        error;
  722.     int            cannot_open;
  723.     linenr_t    line_count;
  724.     int            has_error;
  725.     int            idx;
  726.     int            top;
  727.     int            txt_start;
  728.     long        size;
  729.     int            called_from_main;
  730.     int            serious_error = TRUE;
  731.     long        mtime;
  732.  
  733.     called_from_main = (curbuf->b_ml.ml_mfp == NULL);
  734. /*
  735.  * If the file name ends in ".sw?" we use it directly.
  736.  * Otherwise a search is done to find the swap file(s).
  737.  */
  738.     fname = curbuf->b_xfilename;
  739.     if (fname == NULL)                /* When there is no file name */
  740.         fname = (char_u *)"";
  741.     len = STRLEN(fname);
  742.     if (len >= 4 && vim_strnicmp(fname + len - 4,
  743.                                     (char_u *)".sw", (size_t)3) == 0)
  744.     {
  745.         directly = TRUE;
  746.         fname = strsave(fname);        /* make a copy for mf_open */
  747.     }
  748.     else
  749.     {
  750.         directly = FALSE;
  751.  
  752.             /* count the number of matching swap files */
  753.         len = recover_names(&fname, FALSE, 0);
  754.         if (len == 0)                /* no swap files found */
  755.         {
  756.             EMSG2("No swap file found for %s", fname);
  757.             fname = NULL;
  758.             goto theend;
  759.         }
  760.         if (len == 1)                /* one swap file found, use it */
  761.             i = 1;
  762.         else                        /* several swap files found, choose */
  763.         {
  764.                 /* list the names of the swap files */
  765.             (void)recover_names(&fname, TRUE, 0);
  766.             msg_outchar('\n');
  767.             MSG_OUTSTR("Enter number of swap file to use (0 to quit): ");
  768.             i = get_number();
  769.             if (i < 1 || i > len)
  770.             {
  771.                 fname = NULL;
  772.                 goto theend;
  773.             }
  774.         }
  775.                 /* get the swap file name that will be used */
  776.         (void)recover_names(&fname, FALSE, i);
  777.     }
  778.     if (fname == NULL)
  779.         goto theend;                    /* out of memory */
  780.  
  781.     /* When called from main() still need to initialize storage structure */
  782.     if (called_from_main && ml_open() == FAIL)
  783.         getout(1);
  784.  
  785. /*
  786.  * allocate a buffer structure (only the memline in it is really used)
  787.  */
  788.     buf = (BUF *)alloc((unsigned)sizeof(BUF));
  789.     if (buf == NULL)
  790.         goto theend;
  791.  
  792. /*
  793.  * init fields in memline struct
  794.  */
  795.     buf->b_ml.ml_stack_size = 0;        /* no stack yet */
  796.     buf->b_ml.ml_stack = NULL;            /* no stack yet */
  797.     buf->b_ml.ml_stack_top = 0;            /* nothing in the stack */
  798.     buf->b_ml.ml_line_lnum = 0;            /* no cached line */
  799.     buf->b_ml.ml_locked = NULL;            /* no locked block */
  800.     buf->b_ml.ml_flags = 0;
  801.  
  802. /*
  803.  * open the memfile from the old swap file
  804.  */
  805.     mfp = mf_open(fname, FALSE);
  806.     if (mfp == NULL || mfp->mf_fd < 0)
  807.     {
  808.         EMSG2("Cannot open %s", fname);
  809.         goto theend;
  810.     }
  811.     buf->b_ml.ml_mfp = mfp;
  812. #if defined(MSDOS) || defined(WIN32)
  813.     /*
  814.      * set full pathname for swap file now, because a ":!cd dir" may
  815.      * change directory without us knowing it.
  816.      * Careful: May free fname!
  817.      */
  818.     mf_fullname(mfp);
  819. #endif
  820.  
  821. /*
  822.  * try to read block 0
  823.  */
  824.     if ((hp = mf_get(mfp, (blocknr_t)0, 1)) == NULL)
  825.     {
  826.         msg_start();
  827.         MSG_OUTSTR("Unable to read block 0 from ");
  828.         msg_outtrans(mfp->mf_fname);
  829.         MSG_OUTSTR("\nMaybe no changes were made or Vim did not update the swap file");
  830.         msg_end();
  831.         goto theend;
  832.     }
  833.     b0p = (ZERO_BL *)(hp->bh_data);
  834.     if (b0p->b0_id[0] != BLOCK0_ID0 || b0p->b0_id[1] != BLOCK0_ID1)
  835.     {
  836.         EMSG2("%s is not a swap file", mfp->mf_fname);
  837.         goto theend;
  838.     }
  839.     if (b0_magic_wrong(b0p))
  840.     {
  841.         msg_start();
  842.         MSG_OUTSTR("The file ");
  843.         msg_outtrans(mfp->mf_fname);
  844. #if defined(MSDOS) || defined(WIN32)
  845.         if (STRNCMP(b0p->b0_hname, "PC ", 3) == 0)
  846.             MSG_OUTSTR(" cannot be used with this version of Vim.\n");
  847.         else
  848. #endif
  849.             MSG_OUTSTR(" cannot be used on this computer.\n");
  850.         MSG_OUTSTR("The file was created on ");
  851.                 /* avoid going past the end of currupted hostname */
  852.         b0p->b0_fname[0] = NUL;
  853.         MSG_OUTSTR(b0p->b0_hname);
  854.         MSG_OUTSTR(",\nor the file has been damaged.");
  855.         msg_end();
  856.         goto theend;
  857.     }
  858.     /*
  859.      * If we guessed the wrong page size, we have to recalculate the
  860.      * highest block number in the file.
  861.      */
  862.     if (mfp->mf_page_size != (unsigned)char_to_long(b0p->b0_page_size))
  863.     {
  864.         mfp->mf_page_size = (unsigned)char_to_long(b0p->b0_page_size);
  865.         if ((size = lseek(mfp->mf_fd, 0L, SEEK_END)) <= 0)
  866.             mfp->mf_blocknr_max = 0;        /* no file or empty file */
  867.         else
  868.             mfp->mf_blocknr_max = size / mfp->mf_page_size;
  869.         mfp->mf_infile_count = mfp->mf_blocknr_max;
  870.     }
  871.  
  872. /*
  873.  * If .swp file name given directly, use name from swap file for buffer.
  874.  */
  875.     if (directly)
  876.     {
  877.         expand_env(b0p->b0_fname, NameBuff, MAXPATHL);
  878.         if (setfname(NameBuff, NULL, TRUE) == FAIL)
  879.             goto theend;
  880.     }
  881.  
  882.     home_replace(NULL, mfp->mf_fname, NameBuff, MAXPATHL);
  883.     smsg((char_u *)"Using swap file \"%s\"", NameBuff);
  884.  
  885.     if (curbuf->b_filename == NULL)
  886.         STRCPY(NameBuff, "No File");
  887.     else
  888.         home_replace(NULL, curbuf->b_filename, NameBuff, MAXPATHL);
  889.     smsg((char_u *)"Original file \"%s\"", NameBuff);
  890.     msg_outchar((char_u)'\n');
  891.  
  892. /*
  893.  * check date of swap file and original file
  894.  */
  895.     mtime = char_to_long(b0p->b0_mtime);
  896.     if (curbuf->b_filename != NULL &&
  897.             stat((char *)curbuf->b_filename, &org_stat) != -1 &&
  898.             ((stat((char *)mfp->mf_fname, &swp_stat) != -1 &&
  899.             org_stat.st_mtime > swp_stat.st_mtime) ||
  900.             org_stat.st_mtime != mtime))
  901.     {
  902.         EMSG("Warning: Original file may have been changed");
  903.     }
  904.     flushbuf();
  905.     mf_put(mfp, hp, FALSE, FALSE);        /* release block 0 */
  906.     hp = NULL;
  907.  
  908.     /*
  909.      * Now that we are sure that the file is going to be recovered, clear the
  910.      * contents of the current buffer.
  911.      */
  912.     while (!(curbuf->b_ml.ml_flags & ML_EMPTY))
  913.         ml_delete((linenr_t)1, FALSE);
  914.  
  915.     bnum = 1;            /* start with block 1 */
  916.     page_count = 1;        /* which is 1 page */
  917.     lnum = 0;            /* append after line 0 in curbuf */
  918.     line_count = 0;
  919.     idx = 0;            /* start with first index in block 1 */
  920.     error = 0;
  921.     buf->b_ml.ml_stack_top = 0;
  922.     buf->b_ml.ml_stack = NULL;
  923.     buf->b_ml.ml_stack_size = 0;        /* no stack yet */
  924.  
  925.     if (curbuf->b_filename == NULL)
  926.         cannot_open = TRUE;
  927.     else
  928.         cannot_open = FALSE;
  929.  
  930.     serious_error = FALSE;
  931.     for ( ; !got_int; line_breakcheck())
  932.     {
  933.         if (hp != NULL)
  934.             mf_put(mfp, hp, FALSE, FALSE);        /* release previous block */
  935.  
  936.         /*
  937.          * get block
  938.          */
  939.         if ((hp = mf_get(mfp, (blocknr_t)bnum, page_count)) == NULL)
  940.         {
  941.             if (bnum == 1)
  942.             {
  943.                 EMSG2("Unable to read block 1 from %s", mfp->mf_fname);
  944.                 goto theend;
  945.             }
  946.             ++error;
  947.             ml_append(lnum++, (char_u *)"???MANY LINES MISSING", (colnr_t)0, TRUE);
  948.         }
  949.         else            /* there is a block */
  950.         {
  951.             pp = (PTR_BL *)(hp->bh_data);
  952.             if (pp->pb_id == PTR_ID)            /* it is a pointer block */
  953.             {
  954.                     /* check line count when using pointer block first time */
  955.                 if (idx == 0 && line_count != 0)
  956.                 {
  957.                     for (i = 0; i < (int)pp->pb_count; ++i)
  958.                         line_count -= pp->pb_pointer[i].pe_line_count;
  959.                     if (line_count != 0)
  960.                     {
  961.                         ++error;
  962.                         ml_append(lnum++, (char_u *)"???LINE COUNT WRONG", (colnr_t)0, TRUE);
  963.                     }
  964.                 }
  965.  
  966.                 if (pp->pb_count == 0)
  967.                 {
  968.                     ml_append(lnum++, (char_u *)"???EMPTY BLOCK", (colnr_t)0, TRUE);
  969.                     ++error;
  970.                 }
  971.                 else if (idx < (int)pp->pb_count)        /* go a block deeper */
  972.                 {
  973.                     if (pp->pb_pointer[idx].pe_bnum < 0)
  974.                     {
  975.                         /*
  976.                          * Data block with negative block number.
  977.                          * Try to read lines from the original file.
  978.                          * This is slow, but it works.
  979.                          */
  980.                         if (!cannot_open)
  981.                         {
  982.                             line_count = pp->pb_pointer[idx].pe_line_count;
  983.                             if (readfile(curbuf->b_filename, NULL, lnum, FALSE,
  984.                                         pp->pb_pointer[idx].pe_old_lnum - 1,
  985.                                         line_count, FALSE) == FAIL)
  986.                                 cannot_open = TRUE;
  987.                             else
  988.                                 lnum += line_count;
  989.                         }
  990.                         if (cannot_open)
  991.                         {
  992.                             ++error;
  993.                             ml_append(lnum++, (char_u *)"???LINES MISSING", (colnr_t)0, TRUE);
  994.                         }
  995.                         ++idx;        /* get same block again for next index */
  996.                         continue;
  997.                     }
  998.  
  999.                     /*
  1000.                      * going one block deeper in the tree
  1001.                      */
  1002.                     if ((top = ml_add_stack(buf)) < 0)        /* new entry in stack */
  1003.                     {
  1004.                         ++error;
  1005.                         break;                /* out of memory */
  1006.                     }
  1007.                     ip = &(buf->b_ml.ml_stack[top]);
  1008.                     ip->ip_bnum = bnum;
  1009.                     ip->ip_index = idx;
  1010.  
  1011.                     bnum = pp->pb_pointer[idx].pe_bnum;
  1012.                     line_count = pp->pb_pointer[idx].pe_line_count;
  1013.                     page_count = pp->pb_pointer[idx].pe_page_count;
  1014.                     continue;
  1015.                 }
  1016.             }
  1017.             else            /* not a pointer block */
  1018.             {
  1019.                 dp = (DATA_BL *)(hp->bh_data);
  1020.                 if (dp->db_id != DATA_ID)        /* block id wrong */
  1021.                 {
  1022.                     if (bnum == 1)
  1023.                     {
  1024.                         EMSG2("Block 1 ID wrong (%s not a .swp file?)",
  1025.                                                                mfp->mf_fname);
  1026.                         goto theend;
  1027.                     }
  1028.                     ++error;
  1029.                     ml_append(lnum++, (char_u *)"???BLOCK MISSING", (colnr_t)0, TRUE);
  1030.                 }
  1031.                 else
  1032.                 {
  1033.                     /*
  1034.                      * it is a data block
  1035.                      * Append all the lines in this block
  1036.                      */
  1037.                     has_error = FALSE;
  1038.                         /*
  1039.                          * check length of block
  1040.                          * if wrong, use length in pointer block
  1041.                          */
  1042.                     if (page_count * mfp->mf_page_size != dp->db_txt_end)
  1043.                     {
  1044.                         ml_append(lnum++, (char_u *)"??? from here until ???END lines may be messed up", (colnr_t)0, TRUE);
  1045.                         ++error;
  1046.                         has_error = TRUE;
  1047.                         dp->db_txt_end = page_count * mfp->mf_page_size;
  1048.                     }
  1049.                         
  1050.                         /* make sure there is a NUL at the end of the block */
  1051.                     *((char_u *)dp + dp->db_txt_end - 1) = NUL;
  1052.  
  1053.                         /*
  1054.                          * check number of lines in block
  1055.                          * if wrong, use count in data block
  1056.                          */
  1057.                     if (line_count != dp->db_line_count)
  1058.                     {
  1059.                         ml_append(lnum++, (char_u *)"??? from here until ???END lines may have been inserted/deleted", (colnr_t)0, TRUE);
  1060.                         ++error;
  1061.                         has_error = TRUE;
  1062.                     }
  1063.  
  1064.                     for (i = 0; i < dp->db_line_count; ++i)
  1065.                     {
  1066.                         txt_start = (dp->db_index[i] & DB_INDEX_MASK);
  1067.                         if (txt_start <= HEADER_SIZE || txt_start >= (int)dp->db_txt_end)
  1068.                         {
  1069.                             p = (char_u *)"???";
  1070.                             ++error;
  1071.                         }
  1072.                         else
  1073.                             p = (char_u *)dp + txt_start;
  1074.                         ml_append(lnum++, p, (colnr_t)0, TRUE);
  1075.                     }
  1076.                     if (has_error)
  1077.                         ml_append(lnum++, (char_u *)"???END", (colnr_t)0, TRUE);
  1078.                 }
  1079.             }
  1080.         }
  1081.  
  1082.         if (buf->b_ml.ml_stack_top == 0)        /* finished */
  1083.             break;
  1084.  
  1085.         /*
  1086.          * go one block up in the tree
  1087.          */
  1088.         ip = &(buf->b_ml.ml_stack[--(buf->b_ml.ml_stack_top)]);
  1089.         bnum = ip->ip_bnum;
  1090.         idx = ip->ip_index + 1;        /* go to next index */
  1091.         page_count = 1;
  1092.     }
  1093.  
  1094.     /*
  1095.      * The dummy line from the empty buffer will now be after the last line in
  1096.      * the buffer. Delete it.
  1097.      */
  1098.     ml_delete(curbuf->b_ml.ml_line_count, FALSE);
  1099.  
  1100.     recoverymode = FALSE;
  1101.     if (got_int)
  1102.         EMSG("Recovery Interrupted");
  1103.     else if (error)
  1104.         EMSG("Errors detected while recovering; look for lines starting with ???");
  1105.     else
  1106.     {
  1107.         MSG("Recovery completed. You should check if everything is OK.");
  1108.         MSG_OUTSTR("\n(You might want to write out this file under another name\n");
  1109.         MSG_OUTSTR("and run diff with the original file to check for changes)\n");
  1110.         MSG_OUTSTR("Delete the .swp file afterwards.\n\n");
  1111.         cmdline_row = msg_row;
  1112.     }
  1113.  
  1114. theend:
  1115.     if (mfp != NULL)
  1116.     {
  1117.         if (hp != NULL)
  1118.             mf_put(mfp, hp, FALSE, FALSE);
  1119.         mf_close(mfp, FALSE);        /* will also vim_free(mfp->mf_fname) */
  1120.     }
  1121.     else
  1122.         vim_free(fname);
  1123.     vim_free(buf);
  1124.     if (serious_error && called_from_main)
  1125.         ml_close(curbuf, TRUE);
  1126.     return;
  1127. }
  1128.  
  1129. /*
  1130.  * Find the names of swap files in current directory and the directory given
  1131.  * with the 'directory' option.
  1132.  *
  1133.  * Used to:
  1134.  * - list the swap files for "vim -r"
  1135.  * - count the number of swap files when recovering
  1136.  * - list the swap files when recovering
  1137.  * - find the name of the n'th swap file when recovering
  1138.  */
  1139.     int
  1140. recover_names(fname, list, nr)
  1141.     char_u        **fname;    /* base for swap file name */
  1142.     int            list;        /* when TRUE, list the swap file names */
  1143.     int            nr;            /* when non-zero, return nr'th swap file name */
  1144. {
  1145.     int            num_names;
  1146.     char_u        *(names[6]);
  1147.     char_u        *tail;
  1148.     char_u        *p;
  1149.     int            num_files;
  1150.     int            file_count = 0;
  1151.     char_u        **files;
  1152.     int            i;
  1153.     char_u        *dirp;
  1154.     char_u        *dir_name;
  1155.  
  1156.     if (list)
  1157.     {
  1158.             /* use msg() to start the scrolling properly */
  1159.         msg((char_u *)"Swap files found:");
  1160.         msg_outchar('\n');
  1161.     }
  1162.     expand_interactively = TRUE;
  1163.     /*
  1164.      * Do the loop for every directory in 'directory'.
  1165.      */
  1166.     dirp = p_dir;
  1167.     while (*dirp)
  1168.     {
  1169.         /* find character after directory name */
  1170.         dir_name = dirp;
  1171.         while (*dirp && *dirp != ',')
  1172.             ++dirp;
  1173.         dir_name = strnsave(dir_name, (int)(dirp - dir_name));
  1174.         if (dir_name == NULL)        /* out of memory */
  1175.             break;
  1176.         if (*dir_name == '.')        /* check current dir */
  1177.         {
  1178.             if (fname == NULL || *fname == NULL)
  1179.             {
  1180.                 names[0] = strsave((char_u *)"*.sw?");
  1181. #ifdef UNIX
  1182.                     /* for Unix names starting with a dot are special */
  1183.                 names[1] = strsave((char_u *)".*.sw?");
  1184.                 names[2] = strsave((char_u *)".sw?");
  1185.                 num_names = 3;
  1186. #else
  1187.                 num_names = 1;
  1188. #endif
  1189.             }
  1190.             else
  1191.                 num_names = get_names(names, *fname);
  1192.         }
  1193.         else                        /* check directory dir_name */
  1194.         {
  1195.             if (fname == NULL || *fname == NULL)
  1196.             {
  1197.                 names[0] = concat_fnames(dir_name, (char_u *)"*.sw?", TRUE);
  1198. #ifdef UNIX
  1199.                     /* for Unix names starting with a dot are special */
  1200.                 names[1] = concat_fnames(dir_name, (char_u *)".*.sw?", TRUE);
  1201.                 names[2] = concat_fnames(dir_name, (char_u *)".sw?", TRUE);
  1202.                 num_names = 3;
  1203. #else
  1204.                 num_names = 1;
  1205. #endif
  1206.             }
  1207.             else
  1208.             {
  1209.                 tail = gettail(*fname);
  1210.                 tail = concat_fnames(dir_name, tail, TRUE);
  1211.                 if (tail == NULL)
  1212.                     num_names = 0;
  1213.                 else
  1214.                 {
  1215.                     num_names = get_names(names, tail);
  1216.                     vim_free(tail);
  1217.                 }
  1218.             }
  1219.         }
  1220.  
  1221.             /* check for out-of-memory */
  1222.         for (i = 0; i < num_names; ++i)
  1223.         {
  1224.             if (names[i] == NULL)
  1225.             {
  1226.                 for (i = 0; i < num_names; ++i)
  1227.                     vim_free(names[i]);
  1228.                 num_names = 0;
  1229.             }
  1230.         }
  1231.         if (num_names == 0)
  1232.             num_files = 0;
  1233.         else if (ExpandWildCards(num_names, names,
  1234.                                      &num_files, &files, TRUE, FALSE) == FAIL)
  1235.         {
  1236.             MSG_OUTSTR(files);        /* print error message */
  1237.             num_files = 0;
  1238.         }
  1239.         /*
  1240.          * remove swapfile name of the current buffer, it must be ignored
  1241.          */
  1242.         if (curbuf->b_ml.ml_mfp != NULL &&
  1243.                                 (p = curbuf->b_ml.ml_mfp->mf_fname) != NULL)
  1244.         {
  1245.             for (i = 0; i < num_files; ++i)
  1246.                 if (fullpathcmp(p, files[i]) == FPC_SAME)
  1247.                 {
  1248.                     vim_free(files[i]);
  1249.                     --num_files;
  1250.                     for ( ; i < num_files; ++i)
  1251.                         files[i] = files[i + 1];
  1252.                     break;
  1253.                 }
  1254.         }
  1255.         if (nr)
  1256.         {
  1257.             file_count += num_files;
  1258.             if (nr <= file_count)
  1259.             {
  1260.                 *fname = strsave(files[nr - 1 + num_files - file_count]);
  1261.                 dirp = (char_u *)"";                /* stop searching */
  1262.             }
  1263.         }
  1264.         else if (list)
  1265.         {
  1266.             if (*dir_name == '.')
  1267.             {
  1268.                 if (fname == NULL || *fname == NULL)
  1269.                     MSG_OUTSTR("   In current directory:\n");
  1270.                 else
  1271.                     MSG_OUTSTR("   Using specified name:\n");
  1272.             }
  1273.             else
  1274.             {
  1275.                 MSG_OUTSTR("   In directory ");
  1276.                 msg_home_replace(dir_name);
  1277.                 MSG_OUTSTR(":\n");
  1278.             }
  1279.  
  1280.             if (num_files)
  1281.             {
  1282.                 for (i = 0; i < num_files; ++i)
  1283.                 {
  1284.                     /* print the swap file name */
  1285.                     msg_outnum((long)++file_count);
  1286.                     MSG_OUTSTR(".    ");
  1287.                     msg_outstr(gettail(files[i]));
  1288.                     msg_outchar('\n');
  1289.                     swapfile_info(files[i]);
  1290.                 }
  1291.             }
  1292.             else
  1293.                 MSG_OUTSTR("      -- none --\n");
  1294.             flushbuf();
  1295.         }
  1296.         else
  1297.             file_count += num_files;
  1298.  
  1299.         for (i = 0; i < num_names; ++i)
  1300.             vim_free(names[i]);
  1301.         FreeWild(num_files, files);
  1302.  
  1303.         /* advance dirp to next directory name */
  1304.         vim_free(dir_name);
  1305.         if (*dirp == ',')
  1306.             ++dirp;
  1307.         dirp = skipwhite(dirp);
  1308.     }
  1309.     expand_interactively = FALSE;
  1310.     return file_count;
  1311. }
  1312.  
  1313. /*
  1314.  * Give information about an existing swap file
  1315.  */
  1316.     static void
  1317. swapfile_info(fname)
  1318.     char_u        *fname;
  1319. {
  1320.     struct stat        st;
  1321.     int                fd;
  1322.     struct block0    b0;
  1323.     time_t            x;
  1324.  
  1325.     /* print the swap file date */
  1326.     if (stat((char *)fname, &st) != -1)
  1327.     {
  1328.         MSG_OUTSTR("             dated: ");
  1329.         x = st.st_mtime;                    /* Manx C can't do &st.st_mtime */
  1330.         MSG_OUTSTR(ctime(&x));
  1331.     }
  1332.  
  1333.     /*
  1334.      * print the original file name
  1335.      */
  1336.     fd = open((char *)fname, O_RDONLY | O_EXTRA);
  1337.     if (fd >= 0)
  1338.     {
  1339.         if (read(fd, (char *)&b0, sizeof(b0)) == sizeof(b0))
  1340.         {
  1341.             if (b0.b0_id[0] != BLOCK0_ID0 ||
  1342.                                 b0.b0_id[1] != BLOCK0_ID1)
  1343.                 MSG_OUTSTR("         [is not a swap file]");
  1344.             else
  1345.             {
  1346.                 MSG_OUTSTR("         file name: ");
  1347.                 msg_outstr(b0.b0_fname);
  1348.  
  1349.                 if (*(b0.b0_hname) != NUL)
  1350.                 {
  1351.                     MSG_OUTSTR("\n         host name: ");
  1352.                     msg_outstr(b0.b0_hname);
  1353.                 }
  1354.  
  1355.                 if (*(b0.b0_uname) != NUL)
  1356.                 {
  1357.                     MSG_OUTSTR("\n         user name: ");
  1358.                     msg_outstr(b0.b0_uname);
  1359.                 }
  1360.  
  1361.                 if (char_to_long(b0.b0_pid) != 0L)
  1362.                 {
  1363.                     MSG_OUTSTR("\n        process ID: ");
  1364.                     msg_outnum(char_to_long(b0.b0_pid));
  1365. #if defined(UNIX) || defined(__EMX__)
  1366.                     /* EMX kill() not working correctly, it seems */
  1367.                     if (kill(char_to_long(b0.b0_pid), 0) == 0)
  1368.                         MSG_OUTSTR(" (still running)");
  1369. #endif
  1370.                 }
  1371.  
  1372.                 if (b0_magic_wrong(&b0))
  1373.                 {
  1374. #if defined(MSDOS) || defined(WIN32)
  1375.                     if (STRNCMP(b0.b0_hname, "PC ", 3) == 0)
  1376.                         MSG_OUTSTR("\n         [not usable with this version of Vim]");
  1377.                     else
  1378. #endif
  1379.                         MSG_OUTSTR("\n         [not usable on this computer]");
  1380.                 }
  1381.                     
  1382.             }
  1383.         }
  1384.         else
  1385.             MSG_OUTSTR("         [cannot be read]");
  1386.         close(fd);
  1387.     }
  1388.     else
  1389.         MSG_OUTSTR("         [cannot be opened]");
  1390.     msg_outchar('\n');
  1391. }
  1392.  
  1393.     static int
  1394. get_names(names, fname)
  1395.     char_u **names;
  1396.     char_u    *fname;
  1397. {
  1398.     int        num_names;
  1399.  
  1400. #ifdef SHORT_FNAME
  1401.     /*
  1402.      * (MS-DOS) always short names
  1403.      */
  1404.     names[0] = modname(fname, (char_u *)".sw?");
  1405.     num_names = 1;
  1406. #else /* !SHORT_FNAME */
  1407. # ifdef WIN32
  1408.     /*
  1409.      * (WIN32) never short names
  1410.      */
  1411.     num_names = 1;
  1412.     names[0] = concat_fnames(fname, (char_u *)".sw?", FALSE);
  1413. # else /* !WIN32 */
  1414.     /*
  1415.      * (Not MS-DOS or WIN32) maybe short name, maybe not: try both.
  1416.      * Only use the short name if it is different.
  1417.      */
  1418.  
  1419.     int        i;
  1420.  
  1421.     names[0] = concat_fnames(fname, (char_u *)".sw?", FALSE);
  1422.     i = curbuf->b_shortname;
  1423.     curbuf->b_shortname = TRUE;
  1424.     names[1] = modname(fname, (char_u *)".sw?");
  1425.     curbuf->b_shortname = i;
  1426.     if (STRCMP(names[0], names[1]) == 0)
  1427.     {
  1428.         vim_free(names[1]);
  1429.         num_names = 1;
  1430.     }
  1431.     else
  1432.         num_names = 2;
  1433. # endif /* !WIN32 */
  1434. #endif /* !SHORT_FNAME */
  1435.     return num_names;
  1436. }
  1437.  
  1438. /*
  1439.  * sync all memlines
  1440.  *
  1441.  * If 'check_file' is TRUE, check if original file exists and was not changed.
  1442.  * If 'check_char' is TRUE, stop syncing when character becomes available, but
  1443.  * always sync at least one block.
  1444.  */
  1445.     void
  1446. ml_sync_all(check_file, check_char)
  1447.     int        check_file;
  1448.     int        check_char;
  1449. {
  1450.     BUF                *buf;
  1451.     struct stat        st;
  1452.  
  1453.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  1454.     {
  1455.         if (buf->b_ml.ml_mfp == NULL || buf->b_ml.ml_mfp->mf_fname == NULL)
  1456.             continue;                        /* no file */
  1457.  
  1458.         ml_flush_line(buf);                    /* flush buffered line */
  1459.                                             /* flush locked block */
  1460.         (void)ml_find_line(buf, (linenr_t)0, ML_FLUSH);
  1461.         if (buf->b_changed && check_file && mf_need_trans(buf->b_ml.ml_mfp) &&
  1462.                                     buf->b_filename != NULL)
  1463.         {
  1464.             /*
  1465.              * if original file does not exist anymore or has been changed
  1466.              * call ml_preserve to get rid of all negative numbered blocks
  1467.              */
  1468.             if (stat((char *)buf->b_filename, &st) == -1 ||
  1469.                                 st.st_mtime != buf->b_mtime_read)
  1470.             {
  1471.                 ml_preserve(buf, FALSE);
  1472.                 need_check_timestamps = TRUE;    /* give message later */
  1473.             }
  1474.         }
  1475.         if (buf->b_ml.ml_mfp->mf_dirty)
  1476.         {
  1477.             mf_sync(buf->b_ml.ml_mfp, FALSE, check_char, buf->b_changed);
  1478.             if (check_char && mch_char_avail())    /* character available now */
  1479.                 break;
  1480.         }
  1481.     }
  1482. }
  1483.  
  1484. /*
  1485.  * sync one buffer, including negative blocks
  1486.  *
  1487.  * after this all the blocks are in the swap file
  1488.  *
  1489.  * Used for the :preserve command and when the original file has been
  1490.  * changed or deleted.
  1491.  *
  1492.  * when message is TRUE the success of preserving is reported
  1493.  */
  1494.     void
  1495. ml_preserve(buf, message)
  1496.     BUF        *buf;
  1497.     int        message;
  1498. {
  1499.     BHDR        *hp;
  1500.     linenr_t    lnum;
  1501.     MEMFILE        *mfp = buf->b_ml.ml_mfp;
  1502.     int            status;
  1503.  
  1504.     if (mfp == NULL || mfp->mf_fname == NULL)
  1505.     {
  1506.         if (message)
  1507.             EMSG("Cannot preserve, there is no swap file");
  1508.         return;
  1509.     }
  1510.  
  1511.     ml_flush_line(buf);                                /* flush buffered line */
  1512.     (void)ml_find_line(buf, (linenr_t)0, ML_FLUSH);    /* flush locked block */
  1513.     status = mf_sync(mfp, TRUE, FALSE, TRUE);
  1514.         
  1515.             /* stack is invalid after mf_sync(.., TRUE, ..) */
  1516.     buf->b_ml.ml_stack_top = 0;
  1517.  
  1518.     /*
  1519.      * Some of the data blocks may have been changed from negative to
  1520.      * positive block number. In that case the pointer blocks need to be
  1521.      * updated.
  1522.      *
  1523.      * We don't know in which pointer block the references are, so we visit
  1524.      * all data blocks until there are no more translations to be done (or
  1525.      * we hit the end of the file, which can only happen in case a write fails,
  1526.      * e.g. when file system if full).
  1527.      * ml_find_line() does the work by translating the negative block numbers
  1528.      * when getting the first line of each data block.
  1529.      */
  1530.     if (mf_need_trans(mfp))
  1531.     {
  1532.         lnum = 1;
  1533.         while (mf_need_trans(mfp) && lnum <= buf->b_ml.ml_line_count)
  1534.         {
  1535.             hp = ml_find_line(buf, lnum, ML_FIND);
  1536.             if (hp == NULL)
  1537.             {
  1538.                 status = FAIL;
  1539.                 goto theend;
  1540.             }
  1541.             CHECK(buf->b_ml.ml_locked_low != lnum, "low != lnum");
  1542.             lnum = buf->b_ml.ml_locked_high + 1;
  1543.         }
  1544.         (void)ml_find_line(buf, (linenr_t)0, ML_FLUSH);    /* flush locked block */
  1545.         if (mf_sync(mfp, TRUE, FALSE, TRUE) == FAIL)    /* sync the updated pointer blocks */
  1546.             status = FAIL;
  1547.         buf->b_ml.ml_stack_top = 0;            /* stack is invalid now */
  1548.     }
  1549. theend:
  1550.     if (message)
  1551.     {
  1552.         if (status == OK)
  1553.             MSG("File preserved");
  1554.         else
  1555.             EMSG("Preserve failed");
  1556.     }
  1557. }
  1558.  
  1559. /*
  1560.  * get a pointer to a (read-only copy of a) line 
  1561.  * 
  1562.  * On failure an error message is given and IObuff is returned (to avoid
  1563.  * having to check for error everywhere).
  1564.  */
  1565.     char_u    *
  1566. ml_get(lnum)
  1567.     linenr_t    lnum;
  1568. {
  1569.     return ml_get_buf(curbuf, lnum, FALSE);
  1570. }
  1571.  
  1572. /*
  1573.  * ml_get_pos: get pointer to position 'pos'
  1574.  */
  1575.     char_u *
  1576. ml_get_pos(pos)
  1577.     FPOS    *pos;
  1578. {
  1579.     return (ml_get_buf(curbuf, pos->lnum, FALSE) + pos->col);
  1580. }
  1581.  
  1582. /*
  1583.  * ml_get_pos: get pointer to cursor line.
  1584.  */
  1585.     char_u *
  1586. ml_get_curline()
  1587. {
  1588.     return ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE);
  1589. }
  1590.  
  1591. /*
  1592.  * ml_get_pos: get pointer to cursor position
  1593.  */
  1594.     char_u *
  1595. ml_get_cursor()
  1596. {
  1597.     return (ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE) +
  1598.                                                         curwin->w_cursor.col);
  1599. }
  1600.  
  1601. /*
  1602.  * get a pointer to a line in a specific buffer
  1603.  *
  1604.  *  will_change: if TRUE mark the buffer dirty (chars in the line will be
  1605.  *  changed)
  1606.  */
  1607.     char_u    *
  1608. ml_get_buf(buf, lnum, will_change)
  1609.     BUF            *buf;
  1610.     linenr_t    lnum;
  1611.     int            will_change;            /* line will be changed */
  1612. {
  1613.     BHDR    *hp;
  1614.     DATA_BL    *dp;
  1615.     char_u    *ptr;
  1616.  
  1617.     if (lnum > buf->b_ml.ml_line_count)    /* invalid line number */
  1618.     {
  1619.         EMSGN("ml_get: invalid lnum: %ld", lnum);
  1620. errorret:
  1621.         STRCPY(IObuff, "???");
  1622.         return IObuff;
  1623.     }
  1624.     if (lnum <= 0)                        /* pretend line 0 is line 1 */
  1625.         lnum = 1;
  1626.     
  1627.     if (buf->b_ml.ml_mfp == NULL)        /* there are no lines */
  1628.         return (char_u *)"";
  1629.  
  1630. /*
  1631.  * See if it is the same line as requested last time.
  1632.  * Otherwise may need to flush last used line.
  1633.  */
  1634.     if (buf->b_ml.ml_line_lnum != lnum)
  1635.     {
  1636.         ml_flush_line(buf);
  1637.  
  1638.         /*
  1639.          * find the data block containing the line
  1640.          * This also fills the stack with the blocks from the root to the data block
  1641.          * This also releases any locked block.
  1642.          */
  1643.         if ((hp = ml_find_line(buf, lnum, ML_FIND)) == NULL)
  1644.         {
  1645.             EMSGN("ml_get: cannot find line %ld", lnum);
  1646.             goto errorret;
  1647.         }
  1648.  
  1649.         dp = (DATA_BL *)(hp->bh_data);
  1650.  
  1651.         ptr = (char_u *)dp + ((dp->db_index[lnum - buf->b_ml.ml_locked_low]) & DB_INDEX_MASK);
  1652.         buf->b_ml.ml_line_ptr = ptr;
  1653.         buf->b_ml.ml_line_lnum = lnum;
  1654.         buf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
  1655.     }
  1656.     if (will_change)
  1657.         buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
  1658.  
  1659.     return buf->b_ml.ml_line_ptr;
  1660. }
  1661.  
  1662. /*
  1663.  * Check if a line that was just obtained by a call to ml_get
  1664.  * is in allocated memory.
  1665.  */
  1666.     int
  1667. ml_line_alloced()
  1668. {
  1669.     return (curbuf->b_ml.ml_flags & ML_LINE_DIRTY);
  1670. }
  1671.  
  1672. /*
  1673.  * append a line after lnum (may be 0 to insert a line in front of the file)
  1674.  *
  1675.  *   newfile: TRUE when starting to edit a new file, meaning that pe_old_lnum
  1676.  *                will be set for recovery
  1677.  *
  1678.  * return FAIL for failure, OK otherwise
  1679.  */
  1680.     int
  1681. ml_append(lnum, line, len, newfile)
  1682.     linenr_t    lnum;            /* append after this line (can be 0) */
  1683.     char_u        *line;            /* text of the new line */
  1684.     colnr_t        len;            /* length of new line, including NUL, or 0 */
  1685.     int            newfile;        /* flag, see above */
  1686. {
  1687.      if (curbuf->b_ml.ml_line_lnum != 0)
  1688.         ml_flush_line(curbuf);
  1689.     return ml_append_int(curbuf, lnum, line, len, newfile);
  1690. }
  1691.  
  1692.     static int
  1693. ml_append_int(buf, lnum, line, len, newfile)
  1694.     BUF            *buf;
  1695.     linenr_t    lnum;            /* append after this line (can be 0) */
  1696.     char_u        *line;            /* text of the new line */
  1697.     colnr_t        len;            /* length of line, including NUL, or 0 */
  1698.     int            newfile;        /* flag, see above */
  1699. {
  1700.     int            i;
  1701.     int            line_count;        /* number of indexes in current block */
  1702.     int            offset;
  1703.     int            from, to;
  1704.     int            space_needed;    /* space needed for new line */
  1705.     int            page_size;
  1706.     int            page_count;
  1707.     int            db_idx;            /* index for lnum in data block */
  1708.     BHDR        *hp;
  1709.     MEMFILE        *mfp;
  1710.     DATA_BL        *dp;
  1711.     PTR_BL        *pp;
  1712.     IPTR        *ip;
  1713.  
  1714.                                         /* lnum out of range */
  1715.     if (lnum > buf->b_ml.ml_line_count || buf->b_ml.ml_mfp == NULL)
  1716.         return FAIL;
  1717.     
  1718.     if (lowest_marked && lowest_marked > lnum)
  1719.         lowest_marked = lnum + 1;
  1720.  
  1721.     if (len == 0)
  1722.         len = STRLEN(line) + 1;            /* space needed for the text */
  1723.     space_needed = len + INDEX_SIZE;    /* space needed for text + index */
  1724.  
  1725.     mfp = buf->b_ml.ml_mfp;
  1726.     page_size = mfp->mf_page_size;
  1727.  
  1728. /*
  1729.  * find the data block containing the previous line
  1730.  * This also fills the stack with the blocks from the root to the data block
  1731.  * This also releases any locked block.
  1732.  */
  1733.     if ((hp = ml_find_line(buf, lnum == 0 ? (linenr_t)1 : lnum,
  1734.                                                     ML_INSERT)) == NULL)
  1735.         return FAIL;
  1736.  
  1737.     buf->b_ml.ml_flags &= ~ML_EMPTY;
  1738.  
  1739.     if (lnum == 0)                /* got line one instead, correct db_idx */
  1740.         db_idx = -1;            /* careful, it is negative! */
  1741.     else
  1742.         db_idx = lnum - buf->b_ml.ml_locked_low;
  1743.                 /* get line count before the insertion */
  1744.     line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low;
  1745.  
  1746.     dp = (DATA_BL *)(hp->bh_data);
  1747.  
  1748. /*
  1749.  * If
  1750.  * - there is not enough room in the current block
  1751.  * - appending to the last line in the block
  1752.  * - not appending to the last line in the file
  1753.  * insert in front of the next block.
  1754.  */
  1755.     if ((int)dp->db_free < space_needed && db_idx == line_count - 1 &&
  1756.                                             lnum < buf->b_ml.ml_line_count)
  1757.     {
  1758.         /*
  1759.          * Now that the line is not going to be inserted in the block that we
  1760.          * expected, the line count has to be adjusted in the pointer blocks
  1761.          * by using ml_locked_lineadd.
  1762.          */
  1763.         --(buf->b_ml.ml_locked_lineadd);
  1764.         --(buf->b_ml.ml_locked_high);
  1765.         if ((hp = ml_find_line(buf, lnum + 1, ML_INSERT)) == NULL)
  1766.             return FAIL;
  1767.  
  1768.         db_idx = -1;                /* careful, it is negative! */
  1769.                     /* get line count before the insertion */
  1770.         line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low;
  1771.         CHECK(buf->b_ml.ml_locked_low != lnum + 1, "locked_low != lnum + 1");
  1772.  
  1773.         dp = (DATA_BL *)(hp->bh_data);
  1774.     }
  1775.  
  1776.     ++buf->b_ml.ml_line_count;
  1777.  
  1778.     if ((int)dp->db_free >= space_needed)        /* enough room in data block */
  1779.     {
  1780. /*
  1781.  * Insert new line in existing data block, or in data block allocated above.
  1782.  */
  1783.         dp->db_txt_start -= len;
  1784.         dp->db_free -= space_needed;
  1785.         ++(dp->db_line_count);
  1786.  
  1787.         /*
  1788.          * move the text of the lines that follow to the front
  1789.          * adjust the indexes of the lines that follow
  1790.          */
  1791.         if (line_count > db_idx + 1)        /* if there are following lines */
  1792.         {
  1793.             /*
  1794.              * Offset is the start of the previous line.
  1795.              * This will become the character just after the new line.
  1796.              */
  1797.             if (db_idx < 0)
  1798.                 offset = dp->db_txt_end;
  1799.             else
  1800.                 offset = ((dp->db_index[db_idx]) & DB_INDEX_MASK);
  1801.             vim_memmove((char *)dp + dp->db_txt_start,
  1802.                                           (char *)dp + dp->db_txt_start + len,
  1803.                                  (size_t)(offset - (dp->db_txt_start + len)));
  1804.             for (i = line_count - 1; i > db_idx; --i)
  1805.                 dp->db_index[i + 1] = dp->db_index[i] - len;
  1806.             dp->db_index[db_idx + 1] = offset - len;
  1807.         }
  1808.         else                                /* add line at the end */
  1809.             dp->db_index[db_idx + 1] = dp->db_txt_start;
  1810.  
  1811.         /*
  1812.          * copy the text into the block
  1813.          */
  1814.         vim_memmove((char *)dp + dp->db_index[db_idx + 1], line, (size_t)len);
  1815.  
  1816.         /*
  1817.          * Mark the block dirty.
  1818.          */
  1819.         buf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
  1820.         if (!newfile)
  1821.             buf->b_ml.ml_flags |= ML_LOCKED_POS;
  1822.     }
  1823.     else            /* not enough space in data block */
  1824.     {
  1825. /*
  1826.  * If there is not enough room we have to create a new data block and copy some
  1827.  * lines into it.
  1828.  * Then we have to insert an entry in the pointer block.
  1829.  * If this pointer block also is full, we go up another block, and so on, up
  1830.  * to the root if necessary.
  1831.  * The line counts in the pointer blocks have already been adjusted by
  1832.  * ml_find_line().
  1833.  */
  1834.         long        line_count_left, line_count_right;
  1835.         int            page_count_left, page_count_right;
  1836.         BHDR        *hp_left;
  1837.         BHDR        *hp_right;
  1838.         BHDR        *hp_new;
  1839.         int            lines_moved;
  1840.         int            data_moved = 0;            /* init to shut up gcc */
  1841.         int            total_moved = 0;        /* init to shut up gcc */
  1842.         DATA_BL        *dp_right, *dp_left;
  1843.         int            stack_idx;
  1844.         int            in_left;
  1845.         int            lineadd;
  1846.         blocknr_t    bnum_left, bnum_right;
  1847.         linenr_t    lnum_left, lnum_right;
  1848.         int            pb_idx;
  1849.         PTR_BL        *pp_new;
  1850.  
  1851.         /*
  1852.          * We are going to allocate a new data block. Depending on the
  1853.          * situation it will be put to the left or right of the existing
  1854.          * block.  If possible we put the new line in the left block and move
  1855.          * the lines after it to the right block. Otherwise the new line is
  1856.          * also put in the right block. This method is more efficient when
  1857.          * inserting a lot of lines at one place.
  1858.          */
  1859.         if (db_idx < 0)            /* left block is new, right block is existing */
  1860.         {
  1861.             lines_moved = 0;
  1862.             in_left = TRUE;
  1863.             /* space_needed does not change */
  1864.         }
  1865.         else                    /* left block is existing, right block is new */
  1866.         {
  1867.             lines_moved = line_count - db_idx - 1;
  1868.             if (lines_moved == 0)
  1869.                 in_left = FALSE;        /* put new line in right block */
  1870.                                         /* space_needed does not change */
  1871.             else
  1872.             {
  1873.                 data_moved = ((dp->db_index[db_idx]) & DB_INDEX_MASK) -
  1874.                                                             dp->db_txt_start;
  1875.                 total_moved = data_moved + lines_moved * INDEX_SIZE;
  1876.                 if ((int)dp->db_free + total_moved >= space_needed)
  1877.                 {
  1878.                     in_left = TRUE;        /* put new line in left block */
  1879.                     space_needed = total_moved;
  1880.                 }
  1881.                 else
  1882.                 {
  1883.                     in_left = FALSE;        /* put new line in right block */
  1884.                     space_needed += total_moved;
  1885.                 }
  1886.             }
  1887.         }
  1888.  
  1889.         page_count = ((space_needed + HEADER_SIZE) + page_size - 1) / page_size;
  1890.         if ((hp_new = ml_new_data(mfp, newfile, page_count)) == NULL)
  1891.         {
  1892.                         /* correct line counts in pointer blocks */
  1893.             --(buf->b_ml.ml_locked_lineadd);
  1894.             --(buf->b_ml.ml_locked_high);
  1895.             return FAIL;
  1896.         }
  1897.         if (db_idx < 0)            /* left block is new */
  1898.         {
  1899.             hp_left = hp_new;
  1900.             hp_right = hp;
  1901.             line_count_left = 0;
  1902.             line_count_right = line_count;
  1903.         }
  1904.         else                    /* right block is new */
  1905.         {
  1906.             hp_left = hp;
  1907.             hp_right = hp_new;
  1908.             line_count_left = line_count;
  1909.             line_count_right = 0;
  1910.         }
  1911.         dp_right = (DATA_BL *)(hp_right->bh_data);
  1912.         dp_left = (DATA_BL *)(hp_left->bh_data);
  1913.         bnum_left = hp_left->bh_bnum;
  1914.         bnum_right = hp_right->bh_bnum;
  1915.         page_count_left = hp_left->bh_page_count;
  1916.         page_count_right = hp_right->bh_page_count;
  1917.  
  1918.         /*
  1919.          * May move the new line into the right/new block.
  1920.          */
  1921.         if (!in_left)
  1922.         {
  1923.             dp_right->db_txt_start -= len;
  1924.             dp_right->db_free -= len + INDEX_SIZE;
  1925.             dp_right->db_index[0] = dp_right->db_txt_start;
  1926.             vim_memmove((char *)dp_right + dp_right->db_txt_start,
  1927.                                                            line, (size_t)len);
  1928.             ++line_count_right;
  1929.         }
  1930.         /*
  1931.          * may move lines from the left/old block to the right/new one.
  1932.          */
  1933.         if (lines_moved)
  1934.         {
  1935.             /*
  1936.              */
  1937.             dp_right->db_txt_start -= data_moved;
  1938.             dp_right->db_free -= total_moved;
  1939.             vim_memmove((char *)dp_right + dp_right->db_txt_start,
  1940.                          (char *)dp_left + dp_left->db_txt_start,
  1941.                         (size_t)data_moved);
  1942.             offset = dp_right->db_txt_start - dp_left->db_txt_start;
  1943.             dp_left->db_txt_start += data_moved;
  1944.             dp_left->db_free += total_moved;
  1945.  
  1946.             /*
  1947.              * update indexes in the new block
  1948.              */
  1949.             for (to = line_count_right, from = db_idx + 1;
  1950.                                          from < line_count_left; ++from, ++to)
  1951.                 dp_right->db_index[to] = dp->db_index[from] + offset;
  1952.             line_count_right += lines_moved;
  1953.             line_count_left -= lines_moved;
  1954.         }
  1955.  
  1956.         /*
  1957.          * May move the new line into the left (old or new) block.
  1958.          */
  1959.         if (in_left)
  1960.         {
  1961.             dp_left->db_txt_start -= len;
  1962.             dp_left->db_free -= len + INDEX_SIZE;
  1963.             dp_left->db_index[line_count_left] = dp_left->db_txt_start;
  1964.             vim_memmove((char *)dp_left + dp_left->db_txt_start,
  1965.                                                            line, (size_t)len);
  1966.             ++line_count_left;
  1967.         }
  1968.  
  1969.         if (db_idx < 0)            /* left block is new */
  1970.         {
  1971.             lnum_left = lnum + 1;
  1972.             lnum_right = 0;
  1973.         }
  1974.         else                    /* right block is new */
  1975.         {
  1976.             lnum_left = 0;
  1977.             if (in_left)
  1978.                 lnum_right = lnum + 2;
  1979.             else
  1980.                 lnum_right = lnum + 1;
  1981.         }
  1982.         dp_left->db_line_count = line_count_left;
  1983.         dp_right->db_line_count = line_count_right;
  1984.  
  1985.         /*
  1986.          * release the two data blocks
  1987.          * The new one (hp_new) already has a correct blocknumber.
  1988.          * The old one (hp, in ml_locked) gets a positive blocknumber if
  1989.          * we changed it and we are not editing a new file.
  1990.          */
  1991.         if (lines_moved || in_left)
  1992.             buf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
  1993.         if (!newfile && db_idx >= 0 && in_left)
  1994.             buf->b_ml.ml_flags |= ML_LOCKED_POS;
  1995.         mf_put(mfp, hp_new, TRUE, FALSE);
  1996.  
  1997.         /*
  1998.          * flush the old data block
  1999.          * set ml_locked_lineadd to 0, because the updating of the
  2000.          * pointer blocks is done below
  2001.          */
  2002.         lineadd = buf->b_ml.ml_locked_lineadd;
  2003.         buf->b_ml.ml_locked_lineadd = 0;
  2004.         ml_find_line(buf, (linenr_t)0, ML_FLUSH);    /* flush data block */
  2005.  
  2006.         /*
  2007.          * update pointer blocks for the new data block
  2008.          */
  2009.         for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; --stack_idx)
  2010.         {
  2011.             ip = &(buf->b_ml.ml_stack[stack_idx]);
  2012.             pb_idx = ip->ip_index;
  2013.             if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
  2014.                 return FAIL;
  2015.             pp = (PTR_BL *)(hp->bh_data);    /* must be pointer block */
  2016.             if (pp->pb_id != PTR_ID)
  2017.             {
  2018.                 EMSG("pointer block id wrong 3");
  2019.                 mf_put(mfp, hp, FALSE, FALSE);
  2020.                 return FAIL;
  2021.             }
  2022.             /*
  2023.              * TODO: If the pointer block is full and we are adding at the end
  2024.              * try to insert in front of the next block
  2025.              */
  2026.             if (pp->pb_count < pp->pb_count_max)    /* block not full, add one entry */
  2027.             {
  2028.                 if (pb_idx + 1 < (int)pp->pb_count)
  2029.                     vim_memmove(&pp->pb_pointer[pb_idx + 2],
  2030.                                 &pp->pb_pointer[pb_idx + 1],
  2031.                         (size_t)(pp->pb_count - pb_idx - 1) * sizeof(PTR_EN));
  2032.                 ++pp->pb_count;
  2033.                 pp->pb_pointer[pb_idx].pe_line_count = line_count_left;
  2034.                 pp->pb_pointer[pb_idx].pe_bnum = bnum_left;
  2035.                 pp->pb_pointer[pb_idx].pe_page_count = page_count_left;
  2036.                 pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right;
  2037.                 pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right;
  2038.                 pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right;
  2039.  
  2040.                 if (lnum_left != 0)
  2041.                     pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left;
  2042.                 if (lnum_right != 0)
  2043.                     pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right;
  2044.  
  2045.                 mf_put(mfp, hp, TRUE, FALSE);
  2046.                 buf->b_ml.ml_stack_top = stack_idx + 1;        /* truncate stack */
  2047.  
  2048.                 if (lineadd)
  2049.                 {
  2050.                     --(buf->b_ml.ml_stack_top);
  2051.                         /* fix line count for rest of blocks in the stack */
  2052.                     ml_lineadd(buf, lineadd);
  2053.                                                         /* fix stack itself */
  2054.                     buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high +=
  2055.                                                                       lineadd;
  2056.                     ++(buf->b_ml.ml_stack_top);
  2057.                 }
  2058.  
  2059.                 return OK;
  2060.             }
  2061.             else                        /* pointer block full */
  2062.             {
  2063.                 /*
  2064.                  * split the pointer block
  2065.                  * allocate a new pointer block
  2066.                  * move some of the pointer into the new block
  2067.                  * prepare for updating the parent block
  2068.                  */
  2069.                 for (;;)        /* do this twice when splitting block 1 */
  2070.                 {
  2071.                     hp_new = ml_new_ptr(mfp);
  2072.                     if (hp_new == NULL)        /* TODO: try to fix tree */
  2073.                         return FAIL;
  2074.                     pp_new = (PTR_BL *)(hp_new->bh_data);
  2075.  
  2076.                     if (hp->bh_bnum != 1)
  2077.                         break;
  2078.  
  2079.                     /*
  2080.                      * if block 1 becomes full the tree is given an extra level
  2081.                      * The pointers from block 1 are moved into the new block.
  2082.                      * block 1 is updated to point to the new block
  2083.                      * then continue to split the new block
  2084.                      */
  2085.                     vim_memmove(pp_new, pp, (size_t)page_size);
  2086.                     pp->pb_count = 1;
  2087.                     pp->pb_pointer[0].pe_bnum = hp_new->bh_bnum;
  2088.                     pp->pb_pointer[0].pe_line_count = buf->b_ml.ml_line_count;
  2089.                     pp->pb_pointer[0].pe_old_lnum = 1;
  2090.                     pp->pb_pointer[0].pe_page_count = 1;
  2091.                     mf_put(mfp, hp, TRUE, FALSE);    /* release block 1 */
  2092.                     hp = hp_new;                    /* new block is to be split */
  2093.                     pp = pp_new;
  2094.                     CHECK(stack_idx != 0, "stack_idx should be 0");
  2095.                     ip->ip_index = 0;
  2096.                     ++stack_idx;        /* do block 1 again later */
  2097.                 }
  2098.                 /*
  2099.                  * move the pointers after the current one to the new block
  2100.                  * If there are none, the new entry will be in the new block.
  2101.                  */
  2102.                 total_moved = pp->pb_count - pb_idx - 1;
  2103.                 if (total_moved)
  2104.                 {
  2105.                     vim_memmove(&pp_new->pb_pointer[0],
  2106.                                 &pp->pb_pointer[pb_idx + 1],
  2107.                                 (size_t)(total_moved) * sizeof(PTR_EN));
  2108.                     pp_new->pb_count = total_moved;
  2109.                     pp->pb_count -= total_moved - 1;
  2110.                     pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right;
  2111.                     pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right;
  2112.                     pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right;
  2113.                     if (lnum_right)
  2114.                         pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right;
  2115.                 }
  2116.                 else
  2117.                 {
  2118.                     pp_new->pb_count = 1;
  2119.                     pp_new->pb_pointer[0].pe_bnum = bnum_right;
  2120.                     pp_new->pb_pointer[0].pe_line_count = line_count_right;
  2121.                     pp_new->pb_pointer[0].pe_page_count = page_count_right;
  2122.                     pp_new->pb_pointer[0].pe_old_lnum = lnum_right;
  2123.                 }
  2124.                 pp->pb_pointer[pb_idx].pe_bnum = bnum_left;
  2125.                 pp->pb_pointer[pb_idx].pe_line_count = line_count_left;
  2126.                 pp->pb_pointer[pb_idx].pe_page_count = page_count_left;
  2127.                 if (lnum_left)
  2128.                     pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left;
  2129.                 lnum_left = 0;
  2130.                 lnum_right = 0;
  2131.  
  2132.                 /*
  2133.                  * recompute line counts
  2134.                  */
  2135.                 line_count_right = 0;
  2136.                 for (i = 0; i < (int)pp_new->pb_count; ++i)
  2137.                     line_count_right += pp_new->pb_pointer[i].pe_line_count;
  2138.                 line_count_left = 0;
  2139.                 for (i = 0; i < (int)pp->pb_count; ++i)
  2140.                     line_count_left += pp->pb_pointer[i].pe_line_count;
  2141.  
  2142.                 bnum_left = hp->bh_bnum;
  2143.                 bnum_right = hp_new->bh_bnum;
  2144.                 page_count_left = 1;
  2145.                 page_count_right = 1;
  2146.                 mf_put(mfp, hp, TRUE, FALSE);
  2147.                 mf_put(mfp, hp_new, TRUE, FALSE);
  2148.             }
  2149.         }
  2150.         EMSG("Updated too many blocks?");
  2151.         buf->b_ml.ml_stack_top = 0;        /* invalidate stack */
  2152.     }
  2153.     return OK;
  2154. }
  2155.  
  2156. /*
  2157.  * replace line lnum, with buffering, in current buffer
  2158.  *
  2159.  * If copy is TRUE, make a copy of the line, otherwise the line has been
  2160.  * copied to allocated memory already.
  2161.  *
  2162.  * return FAIL for failure, OK otherwise
  2163.  */
  2164.     int
  2165. ml_replace(lnum, line, copy)
  2166.     linenr_t    lnum;
  2167.     char_u        *line;
  2168.     int            copy;
  2169. {
  2170.     if (line == NULL)            /* just checking... */
  2171.         return FAIL;
  2172.  
  2173.     if (curbuf->b_ml.ml_line_lnum != lnum)            /* other line buffered */
  2174.         ml_flush_line(curbuf);                        /* flush it */
  2175.     else if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY)    /* same line allocated */
  2176.         vim_free(curbuf->b_ml.ml_line_ptr);            /* free it */
  2177.     if (copy && (line = strsave(line)) == NULL)        /* allocate memory */
  2178.         return FAIL;
  2179.     curbuf->b_ml.ml_line_ptr = line;
  2180.     curbuf->b_ml.ml_line_lnum = lnum;
  2181.     curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
  2182.  
  2183.     return OK;
  2184. }
  2185.  
  2186. /*
  2187.  * delete line 'lnum'
  2188.  *
  2189.  * return FAIL for failure, OK otherwise
  2190.  */
  2191.     int
  2192. ml_delete(lnum, message)
  2193.     linenr_t    lnum;
  2194.     int            message;
  2195. {
  2196.     ml_flush_line(curbuf);
  2197.     return ml_delete_int(curbuf, lnum, message);
  2198. }
  2199.  
  2200.     static int
  2201. ml_delete_int(buf, lnum, message)
  2202.     BUF            *buf;
  2203.     linenr_t    lnum;
  2204.     int            message;
  2205. {
  2206.     BHDR    *hp;
  2207.     MEMFILE    *mfp;
  2208.     DATA_BL    *dp;
  2209.     PTR_BL    *pp;
  2210.     IPTR    *ip;
  2211.     int        count;            /* number of entries in block */
  2212.     int        idx;
  2213.     int        stack_idx;
  2214.     int        text_start;
  2215.     int        line_start;
  2216.     int        line_size;
  2217.     int        i;
  2218.  
  2219.     if (lnum < 1 || lnum > buf->b_ml.ml_line_count)
  2220.         return FAIL;
  2221.  
  2222.     if (lowest_marked && lowest_marked > lnum)
  2223.         lowest_marked--;
  2224.  
  2225. /*
  2226.  * If the file becomes empty the last line is replaced by an empty line.
  2227.  */
  2228.     if (buf->b_ml.ml_line_count == 1)        /* file becomes empty */
  2229.     {
  2230.         if (message)
  2231.             keep_msg = no_lines_msg;
  2232.         i = ml_replace((linenr_t)1, (char_u *)"", TRUE);
  2233.         buf->b_ml.ml_flags |= ML_EMPTY;
  2234.         return i;
  2235.     }
  2236.  
  2237. /*
  2238.  * find the data block containing the line
  2239.  * This also fills the stack with the blocks from the root to the data block
  2240.  * This also releases any locked block.
  2241.  */
  2242.     mfp = buf->b_ml.ml_mfp;
  2243.     if (mfp == NULL)
  2244.         return FAIL;
  2245.  
  2246.     if ((hp = ml_find_line(buf, lnum, ML_DELETE)) == NULL)
  2247.         return FAIL;
  2248.  
  2249.     dp = (DATA_BL *)(hp->bh_data);
  2250.             /* compute line count before the delete */
  2251.     count = (long)(buf->b_ml.ml_locked_high) - (long)(buf->b_ml.ml_locked_low) + 2;
  2252.     idx = lnum - buf->b_ml.ml_locked_low;
  2253.  
  2254.     --buf->b_ml.ml_line_count;
  2255.  
  2256. /*
  2257.  * special case: If there is only one line in the data block it becomes empty.
  2258.  * Then we have to remove the entry, pointing to this data block, from the
  2259.  * pointer block. If this pointer block also becomes empty, we go up another
  2260.  * block, and so on, up to the root if necessary.
  2261.  * The line counts in the pointer blocks have already been adjusted by
  2262.  * ml_find_line().
  2263.  */
  2264.     if (count == 1)
  2265.     {
  2266.         mf_free(mfp, hp);        /* free the data block */
  2267.         buf->b_ml.ml_locked = NULL;
  2268.  
  2269.         for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; --stack_idx)
  2270.         {
  2271.             buf->b_ml.ml_stack_top = 0;        /* stack is invalid when failing */
  2272.             ip = &(buf->b_ml.ml_stack[stack_idx]);
  2273.             idx = ip->ip_index;
  2274.             if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
  2275.                 return FAIL;
  2276.             pp = (PTR_BL *)(hp->bh_data);    /* must be pointer block */
  2277.             if (pp->pb_id != PTR_ID)
  2278.             {
  2279.                 EMSG("pointer block id wrong 4");
  2280.                 mf_put(mfp, hp, FALSE, FALSE);
  2281.                 return FAIL;
  2282.             }
  2283.             count = --(pp->pb_count);
  2284.             if (count == 0)            /* the pointer block becomes empty! */
  2285.                 mf_free(mfp, hp);
  2286.             else
  2287.             {
  2288.                 if (count != idx)        /* move entries after the deleted one */
  2289.                     vim_memmove(&pp->pb_pointer[idx], &pp->pb_pointer[idx + 1],
  2290.                                       (size_t)(count - idx) * sizeof(PTR_EN));
  2291.                 mf_put(mfp, hp, TRUE, FALSE);
  2292.  
  2293.                 buf->b_ml.ml_stack_top = stack_idx;        /* truncate stack */
  2294.                     /* fix line count for rest of blocks in the stack */
  2295.                 if (buf->b_ml.ml_locked_lineadd)
  2296.                 {
  2297.                     ml_lineadd(buf, buf->b_ml.ml_locked_lineadd);
  2298.                     buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high +=
  2299.                                                 buf->b_ml.ml_locked_lineadd;
  2300.                 }
  2301.                 ++(buf->b_ml.ml_stack_top);
  2302.  
  2303.                 return OK;
  2304.             }
  2305.         }
  2306.         CHECK(1, "deleted block 1?");
  2307.  
  2308.         return OK;
  2309.     }
  2310.  
  2311.     /*
  2312.      * delete the text by moving the next lines forwards
  2313.      */
  2314.     text_start = dp->db_txt_start;
  2315.     line_start = ((dp->db_index[idx]) & DB_INDEX_MASK);
  2316.     if (idx == 0)                /* first line in block, text at the end */
  2317.         line_size = dp->db_txt_end - line_start;
  2318.     else
  2319.         line_size = ((dp->db_index[idx - 1]) & DB_INDEX_MASK) - line_start;
  2320.     vim_memmove((char *)dp + text_start + line_size, (char *)dp + text_start,
  2321.                                            (size_t)(line_start - text_start));
  2322.  
  2323.     /*
  2324.      * delete the index by moving the next indexes backwards
  2325.      * Adjust the indexes for the text movement.
  2326.      */
  2327.     for (i = idx; i < count - 1; ++i)
  2328.         dp->db_index[i] = dp->db_index[i + 1] + line_size;
  2329.  
  2330.     dp->db_free += line_size + INDEX_SIZE;
  2331.     dp->db_txt_start += line_size;
  2332.     --(dp->db_line_count);
  2333.  
  2334.     /*
  2335.      * mark the block dirty and make sure it is in the file (for recovery)
  2336.      */
  2337.     buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
  2338.  
  2339.     return OK;
  2340. }
  2341.  
  2342. /*
  2343.  * set the B_MARKED flag for line 'lnum'
  2344.  */
  2345.     void
  2346. ml_setmarked(lnum)
  2347.     linenr_t lnum;
  2348. {
  2349.     BHDR    *hp;
  2350.     DATA_BL    *dp;
  2351.                                     /* invalid line number */
  2352.     if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count ||
  2353.                                                 curbuf->b_ml.ml_mfp == NULL)
  2354.         return;                        /* give error message? */
  2355.  
  2356.     if (lowest_marked == 0 || lowest_marked > lnum)
  2357.         lowest_marked = lnum;
  2358.  
  2359.     /*
  2360.      * find the data block containing the line
  2361.      * This also fills the stack with the blocks from the root to the data block
  2362.      * This also releases any locked block.
  2363.      */
  2364.     if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
  2365.         return;                /* give error message? */
  2366.  
  2367.     dp = (DATA_BL *)(hp->bh_data);
  2368.     dp->db_index[lnum - curbuf->b_ml.ml_locked_low] |= DB_MARKED;
  2369.     curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
  2370. }
  2371.  
  2372. /*
  2373.  * find the first line with its B_MARKED flag set
  2374.  */
  2375.     linenr_t
  2376. ml_firstmarked()
  2377. {
  2378.     BHDR        *hp;
  2379.     DATA_BL        *dp;
  2380.     linenr_t    lnum;
  2381.     int            i;
  2382.  
  2383.     if (curbuf->b_ml.ml_mfp == NULL)
  2384.         return (linenr_t) 0;
  2385.  
  2386.     /*
  2387.      * The search starts with lowest_marked line. This is the last line where
  2388.      * a mark was found, adjusted by inserting/deleting lines.
  2389.      */
  2390.     for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; )
  2391.     {
  2392.         /*
  2393.          * Find the data block containing the line.
  2394.          * This also fills the stack with the blocks from the root to the data
  2395.          * block This also releases any locked block.
  2396.          */
  2397.         if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
  2398.             return (linenr_t)0;                /* give error message? */
  2399.  
  2400.         dp = (DATA_BL *)(hp->bh_data);
  2401.  
  2402.         for (i = lnum - curbuf->b_ml.ml_locked_low;
  2403.                             lnum <= curbuf->b_ml.ml_locked_high; ++i, ++lnum)
  2404.             if ((dp->db_index[i]) & DB_MARKED)
  2405.             {
  2406.                 (dp->db_index[i]) &= DB_INDEX_MASK;
  2407.                 curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
  2408.                 lowest_marked = lnum + 1;
  2409.                 return lnum;
  2410.             }
  2411.     }
  2412.  
  2413.     return (linenr_t) 0;
  2414. }
  2415.  
  2416. /*
  2417.  * return TRUE if line 'lnum' has a mark
  2418.  */
  2419.     int
  2420. ml_has_mark(lnum)
  2421.     linenr_t    lnum;
  2422. {
  2423.     BHDR        *hp;
  2424.     DATA_BL        *dp;
  2425.  
  2426.     if (curbuf->b_ml.ml_mfp == NULL ||
  2427.                         (hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
  2428.         return FALSE;
  2429.  
  2430.     dp = (DATA_BL *)(hp->bh_data);
  2431.     return (int)((dp->db_index[lnum - curbuf->b_ml.ml_locked_low]) & DB_MARKED);
  2432. }
  2433.  
  2434. /*
  2435.  * clear all DB_MARKED flags
  2436.  */
  2437.     void
  2438. ml_clearmarked()
  2439. {
  2440.     BHDR        *hp;
  2441.     DATA_BL        *dp;
  2442.     linenr_t    lnum;
  2443.     int            i;
  2444.  
  2445.     if (curbuf->b_ml.ml_mfp == NULL)        /* nothing to do */
  2446.         return;
  2447.  
  2448.     /*
  2449.      * The search starts with line lowest_marked.
  2450.      */
  2451.     for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; )
  2452.     {
  2453.         /*
  2454.          * Find the data block containing the line.
  2455.          * This also fills the stack with the blocks from the root to the data block
  2456.          * This also releases any locked block.
  2457.          */
  2458.         if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
  2459.             return;                /* give error message? */
  2460.  
  2461.         dp = (DATA_BL *)(hp->bh_data);
  2462.  
  2463.         for (i = lnum - curbuf->b_ml.ml_locked_low;
  2464.                             lnum <= curbuf->b_ml.ml_locked_high; ++i, ++lnum)
  2465.             if ((dp->db_index[i]) & DB_MARKED)
  2466.             {
  2467.                 (dp->db_index[i]) &= DB_INDEX_MASK;
  2468.                 curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
  2469.             }
  2470.     }
  2471.  
  2472.     lowest_marked = 0;
  2473.     return;
  2474. }
  2475.  
  2476. /*
  2477.  * flush ml_line if necessary
  2478.  */
  2479.     static void
  2480. ml_flush_line(buf)
  2481.     BUF        *buf;
  2482. {
  2483.     BHDR        *hp;
  2484.     DATA_BL        *dp;
  2485.     linenr_t    lnum;
  2486.     char_u        *new_line;
  2487.     char_u        *old_line;
  2488.     colnr_t        new_len;
  2489.     int            old_len;
  2490.     int            extra;
  2491.     int            idx;
  2492.     int            start;
  2493.     int            count;
  2494.     int            i;
  2495.  
  2496.      if (buf->b_ml.ml_line_lnum == 0 ||
  2497.                         buf->b_ml.ml_mfp == NULL)        /* nothing to do */
  2498.         return;
  2499.  
  2500.     if (buf->b_ml.ml_flags & ML_LINE_DIRTY)
  2501.     {
  2502.         lnum = buf->b_ml.ml_line_lnum;
  2503.         new_line = buf->b_ml.ml_line_ptr;
  2504.  
  2505.         hp = ml_find_line(buf, lnum, ML_FIND);
  2506.         if (hp == NULL)
  2507.             EMSGN("Cannot find line %ld", lnum);
  2508.         else
  2509.         {
  2510.             dp = (DATA_BL *)(hp->bh_data);
  2511.             idx = lnum - buf->b_ml.ml_locked_low;
  2512.             start = ((dp->db_index[idx]) & DB_INDEX_MASK);
  2513.             old_line = (char_u *)dp + start;
  2514.             if (idx == 0)        /* line is last in block */
  2515.                 old_len = dp->db_txt_end - start;
  2516.             else                /* text of previous line follows */
  2517.                 old_len = (dp->db_index[idx - 1] & DB_INDEX_MASK) - start;
  2518.             new_len = STRLEN(new_line) + 1;
  2519.             extra = new_len - old_len;        /* negative if lines gets smaller */
  2520.  
  2521.             /*
  2522.              * if new line fits in data block, replace directly
  2523.              */
  2524.             if ((int)dp->db_free >= extra)
  2525.             {
  2526.                     /* if the length changes and there are following lines */
  2527.                 count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1;
  2528.                 if (extra != 0 && idx < count - 1)
  2529.                 {
  2530.                         /* move text of following lines */
  2531.                     vim_memmove((char *)dp + dp->db_txt_start - extra,
  2532.                                 (char *)dp + dp->db_txt_start,
  2533.                                 (size_t)(start - dp->db_txt_start));
  2534.  
  2535.                         /* adjust pointers of this and following lines */
  2536.                     for (i = idx + 1; i < count; ++i)
  2537.                         dp->db_index[i] -= extra;
  2538.                 }
  2539.                 dp->db_index[idx] -= extra;
  2540.  
  2541.                     /* adjust free space */
  2542.                 dp->db_free -= extra;
  2543.                 dp->db_txt_start -= extra;
  2544.  
  2545.                     /* copy new line into the data block */
  2546.                 vim_memmove(old_line - extra, new_line, (size_t)new_len);
  2547.                 buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
  2548.             }
  2549.             else
  2550.             {
  2551.                 /*
  2552.                  * Cannot do it in one data block: delete and append.
  2553.                  */
  2554.                     /* How about handling errors??? */
  2555.                 (void)ml_delete_int(buf, lnum, FALSE);
  2556.                 (void)ml_append_int(buf, lnum - 1, new_line, new_len, FALSE);
  2557.             }
  2558.         }
  2559.         vim_free(new_line);
  2560.     }
  2561.  
  2562.     buf->b_ml.ml_line_lnum = 0;
  2563. }
  2564.  
  2565. /*
  2566.  * create a new, empty, data block
  2567.  */
  2568.     static BHDR *
  2569. ml_new_data(mfp, negative, page_count)
  2570.     MEMFILE        *mfp;
  2571.     int            negative;
  2572.     int            page_count;
  2573. {
  2574.     BHDR        *hp;
  2575.     DATA_BL        *dp;
  2576.  
  2577.     if ((hp = mf_new(mfp, negative, page_count)) == NULL)
  2578.         return NULL;
  2579.     
  2580.     dp = (DATA_BL *)(hp->bh_data);
  2581.     dp->db_id = DATA_ID;
  2582.     dp->db_txt_start = dp->db_txt_end = page_count * mfp->mf_page_size;
  2583.     dp->db_free = dp->db_txt_start - HEADER_SIZE;
  2584.     dp->db_line_count = 0;
  2585.  
  2586.     return hp;
  2587. }
  2588.  
  2589. /*
  2590.  * create a new, empty, pointer block
  2591.  */
  2592.     static BHDR *
  2593. ml_new_ptr(mfp)
  2594.     MEMFILE        *mfp;
  2595. {
  2596.     BHDR        *hp;
  2597.     PTR_BL        *pp;
  2598.  
  2599.     if ((hp = mf_new(mfp, FALSE, 1)) == NULL)
  2600.         return NULL;
  2601.     
  2602.     pp = (PTR_BL *)(hp->bh_data);
  2603.     pp->pb_id = PTR_ID;
  2604.     pp->pb_count = 0;
  2605.     pp->pb_count_max = (mfp->mf_page_size - sizeof(PTR_BL)) / sizeof(PTR_EN) + 1;
  2606.  
  2607.     return hp;
  2608. }
  2609.  
  2610. /*
  2611.  * lookup line 'lnum' in a memline
  2612.  *
  2613.  *   action: if ML_DELETE or ML_INSERT the line count is updated while searching
  2614.  *             if ML_FLUSH only flush a locked block
  2615.  *             if ML_FIND just find the line
  2616.  *
  2617.  * If the block was found it is locked and put in ml_locked.
  2618.  * The stack is updated to lead to the locked block. The ip_high field in
  2619.  * the stack is updated to reflect the last line in the block AFTER the
  2620.  * insert or delete, also if the pointer block has not been updated yet. But
  2621.  * if if ml_locked != NULL ml_locked_lineadd must be added to ip_high.
  2622.  *
  2623.  * return: NULL for failure, pointer to block header otherwise
  2624.  */
  2625.     static BHDR *
  2626. ml_find_line(buf, lnum, action)
  2627.     BUF            *buf;
  2628.     linenr_t    lnum;
  2629.     int            action;
  2630. {
  2631.     DATA_BL        *dp;
  2632.     PTR_BL        *pp;
  2633.     IPTR        *ip;
  2634.     BHDR        *hp;
  2635.     MEMFILE        *mfp;
  2636.     linenr_t    t;
  2637.     blocknr_t    bnum, bnum2;
  2638.     int            dirty;
  2639.     linenr_t    low, high;
  2640.     int            top;
  2641.     int            page_count;
  2642.     int            idx;
  2643.  
  2644.     mfp = buf->b_ml.ml_mfp;
  2645.  
  2646.     /*
  2647.      * If there is a locked block check if the wanted line is in it.
  2648.      * If not, flush and release the locked block.
  2649.      * Don't do this for ML_INSERT_SAME, because the stack need to be updated.
  2650.      * Don't do this for ML_FLUSH, because we want to flush the locked block.
  2651.      */
  2652.     if (buf->b_ml.ml_locked)
  2653.     {
  2654.         if (ML_SIMPLE(action) && buf->b_ml.ml_locked_low <= lnum &&
  2655.                                     buf->b_ml.ml_locked_high >= lnum)
  2656.         {
  2657.                 /* remember to update pointer blocks and stack later */
  2658.             if (action == ML_INSERT)
  2659.             {
  2660.                 ++(buf->b_ml.ml_locked_lineadd);
  2661.                 ++(buf->b_ml.ml_locked_high);
  2662.             }
  2663.             else if (action == ML_DELETE)
  2664.             {
  2665.                 --(buf->b_ml.ml_locked_lineadd);
  2666.                 --(buf->b_ml.ml_locked_high);
  2667.             }
  2668.             return (buf->b_ml.ml_locked);
  2669.         }
  2670.  
  2671.         mf_put(mfp, buf->b_ml.ml_locked, buf->b_ml.ml_flags & ML_LOCKED_DIRTY,
  2672.                                             buf->b_ml.ml_flags & ML_LOCKED_POS);
  2673.         buf->b_ml.ml_locked = NULL;
  2674.  
  2675.             /*
  2676.              * if lines have been added or deleted in the locked block, need to
  2677.              * update the line count in pointer blocks
  2678.              */
  2679.         if (buf->b_ml.ml_locked_lineadd)
  2680.             ml_lineadd(buf, buf->b_ml.ml_locked_lineadd);
  2681.     }
  2682.  
  2683.     if (action == ML_FLUSH)            /* nothing else to do */
  2684.         return NULL;
  2685.  
  2686.     bnum = 1;                        /* start at the root of the tree */
  2687.     page_count = 1;
  2688.     low = 1;
  2689.     high = buf->b_ml.ml_line_count;
  2690.  
  2691.     if (action == ML_FIND)        /* first try stack entries */
  2692.     {
  2693.         for (top = buf->b_ml.ml_stack_top - 1; top >= 0; --top)
  2694.         {
  2695.             ip = &(buf->b_ml.ml_stack[top]);
  2696.             if (ip->ip_low <= lnum && ip->ip_high >= lnum)
  2697.             {
  2698.                 bnum = ip->ip_bnum;
  2699.                 low = ip->ip_low;
  2700.                 high = ip->ip_high;
  2701.                 buf->b_ml.ml_stack_top = top;    /* truncate stack at prev entry */
  2702.                 break;
  2703.             }
  2704.         }
  2705.         if (top < 0)
  2706.             buf->b_ml.ml_stack_top = 0;            /* not found, start at the root */
  2707.     }
  2708.     else        /* ML_DELETE or ML_INSERT */
  2709.         buf->b_ml.ml_stack_top = 0;        /* start at the root */
  2710.  
  2711. /*
  2712.  * search downwards in the tree until a data block is found
  2713.  */
  2714.     for (;;)
  2715.     {
  2716.         if ((hp = mf_get(mfp, bnum, page_count)) == NULL)
  2717.             goto error_noblock;
  2718.  
  2719.         /*
  2720.          * update high for insert/delete
  2721.          */
  2722.         if (action == ML_INSERT)
  2723.             ++high;
  2724.         else if (action == ML_DELETE)
  2725.             --high;
  2726.  
  2727.         dp = (DATA_BL *)(hp->bh_data);
  2728.         if (dp->db_id == DATA_ID)        /* data block */
  2729.         {
  2730.             buf->b_ml.ml_locked = hp;
  2731.             buf->b_ml.ml_locked_low = low;
  2732.             buf->b_ml.ml_locked_high = high;
  2733.             buf->b_ml.ml_locked_lineadd = 0;
  2734.             buf->b_ml.ml_flags &= ~(ML_LOCKED_DIRTY | ML_LOCKED_POS);
  2735.             return hp;
  2736.         }
  2737.  
  2738.         pp = (PTR_BL *)(dp);            /* must be pointer block */
  2739.         if (pp->pb_id != PTR_ID)
  2740.         {
  2741.             EMSG("pointer block id wrong");
  2742.             goto error_block;
  2743.         }
  2744.  
  2745.         if ((top = ml_add_stack(buf)) < 0)        /* add new entry to stack */
  2746.             goto error_block;
  2747.         ip = &(buf->b_ml.ml_stack[top]);
  2748.         ip->ip_bnum = bnum;
  2749.         ip->ip_low = low;
  2750.         ip->ip_high = high;
  2751.         ip->ip_index = -1;                /* index not known yet */
  2752.  
  2753.         dirty = FALSE;
  2754.         for (idx = 0; idx < (int)pp->pb_count; ++idx)
  2755.         {
  2756.             t = pp->pb_pointer[idx].pe_line_count;
  2757.             CHECK(t == 0, "pe_line_count is zero");
  2758.             if ((low += t) > lnum)
  2759.             {
  2760.                 ip->ip_index = idx;
  2761.                 bnum = pp->pb_pointer[idx].pe_bnum;
  2762.                 page_count = pp->pb_pointer[idx].pe_page_count;
  2763.                 high = low - 1;
  2764.                 low -= t;
  2765.  
  2766.                 /*
  2767.                  * a negative block number may have been changed
  2768.                  */
  2769.                 if (bnum < 0)
  2770.                 {
  2771.                     bnum2 = mf_trans_del(mfp, bnum);
  2772.                     if (bnum != bnum2)
  2773.                     {
  2774.                         bnum = bnum2;
  2775.                         pp->pb_pointer[idx].pe_bnum = bnum;
  2776.                         dirty = TRUE;
  2777.                     }
  2778.                 }
  2779.  
  2780.                 break;
  2781.             }
  2782.         }
  2783.         if (idx >= (int)pp->pb_count)        /* past the end: something wrong! */
  2784.         {
  2785.             if (lnum > buf->b_ml.ml_line_count)
  2786.                 EMSGN("line number out of range: %ld past the end",
  2787.                                               lnum - buf->b_ml.ml_line_count);
  2788.  
  2789.             else
  2790.                 EMSGN("line count wrong in block %ld", bnum);
  2791.             goto error_block;
  2792.         }
  2793.         if (action == ML_DELETE)
  2794.         {
  2795.             pp->pb_pointer[idx].pe_line_count--;
  2796.             dirty = TRUE;
  2797.         }
  2798.         else if (action == ML_INSERT)
  2799.         {
  2800.             pp->pb_pointer[idx].pe_line_count++;
  2801.             dirty = TRUE;
  2802.         }
  2803.         mf_put(mfp, hp, dirty, FALSE);
  2804.     }
  2805.  
  2806. error_block:
  2807.     mf_put(mfp, hp, FALSE, FALSE);
  2808. error_noblock:
  2809. /*
  2810.  * If action is ML_DELETE or ML_INSERT we have to correct the tree for
  2811.  * the incremented/decremented line counts, because there won't be a line
  2812.  * inserted/deleted after all.
  2813.  */
  2814.     if (action == ML_DELETE)
  2815.         ml_lineadd(buf, 1);
  2816.     else if (action == ML_INSERT)
  2817.         ml_lineadd(buf, -1);
  2818.     buf->b_ml.ml_stack_top = 0;
  2819.     return NULL;
  2820. }
  2821.  
  2822. /*
  2823.  * add an entry to the info pointer stack
  2824.  *
  2825.  * return -1 for failure, number of the new entry otherwise
  2826.  */
  2827.     static int
  2828. ml_add_stack(buf)
  2829.     BUF        *buf;
  2830. {
  2831.     int        top;
  2832.     IPTR    *newstack;
  2833.  
  2834.     top = buf->b_ml.ml_stack_top;
  2835.  
  2836.         /* may have to increase the stack size */
  2837.     if (top == buf->b_ml.ml_stack_size)
  2838.     {
  2839.         CHECK(top > 0, "Stack size increases");    /* more than 5 levels??? */
  2840.  
  2841.         newstack = (IPTR *)alloc((unsigned)sizeof(IPTR) *
  2842.                                         (buf->b_ml.ml_stack_size + STACK_INCR));
  2843.         if (newstack == NULL)
  2844.             return -1;
  2845.         vim_memmove(newstack, buf->b_ml.ml_stack, (size_t)top * sizeof(IPTR));
  2846.         vim_free(buf->b_ml.ml_stack);
  2847.         buf->b_ml.ml_stack = newstack;
  2848.         buf->b_ml.ml_stack_size += STACK_INCR;
  2849.     }
  2850.  
  2851.     buf->b_ml.ml_stack_top++;
  2852.     return top;
  2853. }
  2854.  
  2855. /*
  2856.  * Update the pointer blocks on the stack for inserted/deleted lines.
  2857.  * The stack itself is also updated.
  2858.  *
  2859.  * When a insert/delete line action fails, the line is not inserted/deleted,
  2860.  * but the pointer blocks have already been updated. That is fixed here by
  2861.  * walking through the stack.
  2862.  *
  2863.  * Count is the number of lines added, negative if lines have been deleted.
  2864.  */
  2865.     static void
  2866. ml_lineadd(buf, count)
  2867.     BUF            *buf;
  2868.     int            count;
  2869. {
  2870.     int            idx;
  2871.     IPTR        *ip;
  2872.     PTR_BL        *pp;
  2873.     MEMFILE        *mfp = buf->b_ml.ml_mfp;
  2874.     BHDR        *hp;
  2875.  
  2876.     for (idx = buf->b_ml.ml_stack_top - 1; idx >= 0; --idx)
  2877.     {
  2878.         ip = &(buf->b_ml.ml_stack[idx]);
  2879.         if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
  2880.             break;
  2881.         pp = (PTR_BL *)(hp->bh_data);    /* must be pointer block */
  2882.         if (pp->pb_id != PTR_ID)
  2883.         {
  2884.             mf_put(mfp, hp, FALSE, FALSE);
  2885.             EMSG("pointer block id wrong 2");
  2886.             break;
  2887.         }
  2888.         pp->pb_pointer[ip->ip_index].pe_line_count += count;
  2889.         ip->ip_high += count;
  2890.         mf_put(mfp, hp, TRUE, FALSE);
  2891.     }
  2892. }
  2893.  
  2894. /*
  2895.  * make swap file name out of the filename and a directory name
  2896.  */
  2897.     static char_u *
  2898. makeswapname(buf, dir_name)
  2899.     BUF        *buf;
  2900.     char_u    *dir_name;
  2901. {
  2902.     char_u        *r, *s, *fname;
  2903.  
  2904. #ifdef VMS
  2905.     r = modname(buf->b_xfilename, (char_u *)"_swp");
  2906. #else
  2907.     r = modname(buf->b_xfilename, (char_u *)".swp");
  2908. #endif
  2909.     /*
  2910.      * do not use dir_name
  2911.      * - if dir_name starts with '.' (use current directory)
  2912.      * - if out of memory
  2913.      */
  2914.     if (*dir_name == '.' || r == NULL)
  2915.         return r;
  2916.  
  2917.     fname = gettail(r);
  2918.     s = concat_fnames(dir_name, fname, TRUE);
  2919.     vim_free(r);
  2920.     return s;
  2921. }
  2922.  
  2923. /*
  2924.  * Find out what name to use for the swap file for buffer 'buf'.
  2925.  *
  2926.  * Several names are tried to find one that does not exist
  2927.  *
  2928.  * Note: if MAXNAMLEN is not correct, you will get error messages for
  2929.  *       not being able to open the swapfile
  2930.  */
  2931.     static char_u *
  2932. findswapname(buf, dirp, old_fname)
  2933.     BUF        *buf;
  2934.     char_u    **dirp;            /* pointer to list of directories */
  2935.     char_u    *old_fname;        /* don't give warning for this filename */
  2936. {
  2937.     char_u        *fname;
  2938.     int            n;
  2939.     time_t        x;
  2940.     char_u        *dir_name;
  2941.  
  2942. #ifdef AMIGA
  2943.     BPTR        fh;
  2944. #endif
  2945.  
  2946. #ifndef SHORT_FNAME
  2947.     int            r;
  2948.     FILE        *dummyfd = NULL;
  2949.  
  2950. /*
  2951.  * If we start editing a new file, e.g. "test.doc", which resides on an MSDOS
  2952.  * compatible filesystem, it is possible that the file "test.doc.swp" which we
  2953.  * create will be exactly the same file. To avoid this problem we temporarily
  2954.  * create "test.doc".
  2955.  */
  2956.     if (!(buf->b_p_sn || buf->b_shortname) && buf->b_xfilename &&
  2957.                                                 getperm(buf->b_xfilename) < 0)
  2958.         dummyfd = fopen((char *)buf->b_xfilename, "w");
  2959. #endif
  2960.  
  2961. /*
  2962.  * Isolate a directory name from *dirp and put it in dir_name.
  2963.  * First allocate some memore to put the directory name in.
  2964.  */
  2965.     dir_name = alloc((unsigned)STRLEN(*dirp) + 1);
  2966.     if (dir_name != NULL)
  2967.         (void)copy_option_part(dirp, dir_name, 31000, ",");
  2968.  
  2969. /*
  2970.  * we try different names until we find one that does not exist yet
  2971.  */
  2972.     if (dir_name == NULL)            /* out of memory */
  2973.         fname = NULL;
  2974.     else
  2975.         fname = makeswapname(buf, dir_name);
  2976.  
  2977.     for (;;)
  2978.     {
  2979.         if (fname == NULL)        /* must be out of memory */
  2980.             break;
  2981.         if ((n = STRLEN(fname)) == 0)    /* safety check */
  2982.         {
  2983.             vim_free(fname);
  2984.             fname = NULL;
  2985.             break;
  2986.         }
  2987. #if (defined(UNIX) || defined(OS2)) && !defined(ARCHIE) && !defined(SHORT_FNAME)
  2988. /*
  2989.  * Some systems have a MS-DOS compatible filesystem that use 8.3 character
  2990.  * file names. If this is the first try and the swap file name does not fit in
  2991.  * 8.3, detect if this is the case, set shortname and try again.
  2992.  */
  2993.         if (fname[n - 1] == 'p' && !(buf->b_p_sn || buf->b_shortname))
  2994.         {
  2995.             char_u            *tail;
  2996.             char_u            *fname2;
  2997.             struct stat        s1, s2;
  2998.             int                f1, f2;
  2999.             int                created1 = FALSE, created2 = FALSE;
  3000.             int                same = FALSE;
  3001.  
  3002.             /*
  3003.              * Check if swapfilename does not fit in 8.3:
  3004.              * It either contains two dots or it is longer than 8 chars.
  3005.              */
  3006.             tail = gettail(buf->b_xfilename);
  3007.             if (vim_strchr(tail, '.') != NULL || STRLEN(tail) > (size_t)8)
  3008.             {
  3009.                 fname2 = alloc(n + 1);
  3010.                 if (fname2 != NULL)
  3011.                 {
  3012.                     STRCPY(fname2, fname);
  3013.                     if (vim_strchr(tail, '.') != NULL)
  3014.                         fname2[n - 1] = 'x';    /* change ".swp" to ".swx" */
  3015.                     else
  3016.                         fname2[n - 5] += 1;        /* change "x.swp" to "y.swp" */
  3017.                     /*
  3018.                      * may need to create the files to be able to use stat()
  3019.                      */
  3020.                     f1 = open((char *)fname, O_RDONLY | O_EXTRA);
  3021.                     if (f1 < 0)
  3022.                     {
  3023.                         f1 = open((char *)fname, O_RDWR|O_CREAT|O_EXCL|O_EXTRA
  3024. #ifdef AMIGA                /* Amiga has no mode argument */
  3025.                                                                             );
  3026. #endif
  3027. #ifdef UNIX                    /* open in rw------- mode */
  3028.                                                               , (mode_t)0600);
  3029. #endif
  3030. #if defined(MSDOS) || defined(WIN32) || defined(OS2)  /* open read/write */
  3031.                                                         , S_IREAD | S_IWRITE);
  3032. #endif
  3033. #if defined(OS2)
  3034.                         if (f1 < 0 && errno == ENOENT)
  3035.                             same = TRUE;
  3036. #endif
  3037.                         created1 = TRUE;
  3038.                     }
  3039.                     if (f1 >= 0)
  3040.                     {
  3041.                         f2 = open((char *)fname2, O_RDONLY | O_EXTRA);
  3042.                         if (f2 < 0)
  3043.                         {
  3044.                             f2 = open((char *)fname2,
  3045.                                                  O_RDWR|O_CREAT|O_EXCL|O_EXTRA
  3046. #ifdef AMIGA                /* Amiga has no mode argument */
  3047.                                                                             );
  3048. #endif
  3049. #ifdef UNIX                    /* open in rw------- mode */
  3050.                                                               , (mode_t)0600);
  3051. #endif
  3052. #if defined(MSDOS) || defined(WIN32) || defined(OS2)  /* open read/write */
  3053.                                                         , S_IREAD | S_IWRITE);
  3054. #endif
  3055.                             created2 = TRUE;
  3056.                         }
  3057.                         if (f2 >= 0)
  3058.                         {
  3059.                             /*
  3060.                              * Both files exist now. If stat() returns the
  3061.                              * same device and inode they are the same file.
  3062.                              */
  3063.                             if (fstat(f1, &s1) != -1 &&
  3064.                                         fstat(f2, &s2) != -1 &&
  3065.                                         s1.st_dev == s2.st_dev &&
  3066.                                         s1.st_ino == s2.st_ino)
  3067.                                 same = TRUE;
  3068.                             close(f2);
  3069.                             if (created2)
  3070.                                 vim_remove(fname2);
  3071.                         }
  3072.                         close(f1);
  3073.                         if (created1)
  3074.                             vim_remove(fname);
  3075.                     }
  3076.                     vim_free(fname2);
  3077.                     if (same)
  3078.                     {
  3079.                         buf->b_shortname = TRUE;
  3080.                         vim_free(fname);
  3081.                         fname = makeswapname(buf, dir_name);
  3082.                         continue;        /* try again with b_shortname set */
  3083.                     }
  3084.                 }
  3085.             }
  3086.         }
  3087. #endif
  3088.         /*
  3089.          * check if the swapfile already exists
  3090.          */
  3091.         if (getperm(fname) < 0)        /* it does not exist */
  3092.         {
  3093. #ifdef AMIGA
  3094.             fh = Open((UBYTE *)fname, (long)MODE_NEWFILE);
  3095.             /*
  3096.              * on the Amiga getperm() will return -1 when the file exists but
  3097.              * is being used by another program. This happens if you edit
  3098.              * a file twice.
  3099.              */
  3100.             if (fh != (BPTR)NULL)        /* can open file, OK */
  3101.             {
  3102.                 Close(fh);
  3103.                 break;
  3104.             }
  3105.             if (IoErr() != ERROR_OBJECT_IN_USE &&
  3106.                                                IoErr() != ERROR_OBJECT_EXISTS)
  3107. #endif
  3108.                 break;
  3109.         }
  3110.         /*
  3111.          * A file name equal to old_fname is OK to use.
  3112.          */
  3113.         if (old_fname != NULL && fnamecmp(fname, old_fname) == 0)
  3114.             break;
  3115.  
  3116.         /*
  3117.          * get here when file already exists
  3118.          */
  3119.         if (fname[n - 1] == 'p')        /* first try */
  3120.         {
  3121. #ifndef SHORT_FNAME
  3122.             /*
  3123.              * on MS-DOS compatible filesystems (e.g. messydos) file.doc.swp
  3124.              * and file.doc are the same file. To guess if this problem is
  3125.              * present try if file.doc.swx exists. If it does, we set
  3126.              * buf->b_shortname and try file_doc.swp (dots replaced by
  3127.              * underscores for this file), and try again. If it doesn't we
  3128.              * assume that "file.doc.swp" already exists.
  3129.              */
  3130.             if (!(buf->b_p_sn || buf->b_shortname))        /* not tried yet */
  3131.             {
  3132.                 fname[n - 1] = 'x';
  3133.                 r = getperm(fname);            /* try "file.swx" */
  3134.                 fname[n - 1] = 'p';
  3135.                 if (r >= 0)                    /* "file.swx" seems to exist */
  3136.                 {
  3137.                     buf->b_shortname = TRUE;
  3138.                     vim_free(fname);
  3139.                     fname = makeswapname(buf, dir_name);
  3140.                     continue;        /* try again with '.' replaced by '_' */
  3141.                 }
  3142.             }
  3143. #endif
  3144.             /*
  3145.              * If we get here the ".swp" file really exists.
  3146.              * Give an error message, unless recovering, no file name, we are
  3147.              * viewing a help file or when the path of the file is different
  3148.              * (happens when all .swp files are in one directory).
  3149.              */
  3150.             if (!recoverymode && buf->b_xfilename != NULL && !buf->b_help)
  3151.             {
  3152.                 int                fd;
  3153.                 struct block0    b0;
  3154.                 int                differ = FALSE;
  3155.  
  3156.                 /*
  3157.                  * Try to read block 0 from the swap file to get the original
  3158.                  * file name (and inode number).
  3159.                  */
  3160.                 fd = open((char *)fname, O_RDONLY | O_EXTRA);
  3161.                 if (fd >= 0)
  3162.                 {
  3163.                     if (read(fd, (char *)&b0, sizeof(b0)) == sizeof(b0))
  3164.                     {
  3165.                         /*
  3166.                          * The name in the swap file may be "~user/path/file".
  3167.                          * Expand it first.
  3168.                          */
  3169.                         expand_env(b0.b0_fname, NameBuff, MAXPATHL);
  3170. #ifdef CHECK_INODE
  3171.                         if (fnamecmp_ino(buf->b_filename, NameBuff,
  3172.                                                      char_to_long(b0.b0_ino)))
  3173.                             differ = TRUE;
  3174. #else
  3175.                         if (fnamecmp(NameBuff, buf->b_filename) != 0)
  3176.                             differ = TRUE;
  3177. #endif
  3178.                     }
  3179.                     close(fd);
  3180.                 }
  3181.                 if (differ == FALSE)
  3182.                 {
  3183.                     struct stat st;
  3184.  
  3185.                     ++no_wait_return;
  3186. #ifdef SLEEP_IN_EMSG
  3187.                     ++dont_sleep;
  3188. #endif
  3189.                     (void)EMSG("ATTENTION");
  3190. #ifdef SLEEP_IN_EMSG
  3191.                     --dont_sleep;
  3192. #endif
  3193.                     MSG_OUTSTR("\nFound a swap file by the name \"");
  3194.                     msg_home_replace(fname);
  3195.                     MSG_OUTSTR("\"\n");
  3196.                     swapfile_info(fname);
  3197.                     MSG_OUTSTR("While opening file \"");
  3198.                     msg_outtrans(buf->b_xfilename);
  3199.                     MSG_OUTSTR("\"\n");
  3200.                     if (stat((char *)buf->b_xfilename, &st) != -1)
  3201.                     {
  3202.                         MSG_OUTSTR("             dated: ");
  3203.                         x = st.st_mtime;    /* Manx C can't do &st.st_mtime */
  3204.                         MSG_OUTSTR(ctime(&x));
  3205.                     }
  3206.                     MSG_OUTSTR("\n(1) Another program may be editing the same file.\n");
  3207.                     MSG_OUTSTR("    If this is the case, quit this edit session to avoid having\n");
  3208.                     MSG_OUTSTR("    two different instances of the same file when making changes.\n");
  3209.                     MSG_OUTSTR("\n(2) An edit session for this file crashed.\n");
  3210.                     MSG_OUTSTR("    If this is the case, use \":recover\" or \"vim -r ");
  3211.                     msg_outtrans(buf->b_xfilename);
  3212.                     MSG_OUTSTR("\"\n    to recover the changes (see \":help recovery)\".\n");
  3213.                     MSG_OUTSTR("    If you did this already, delete the swap file \"");
  3214.                     msg_outtrans(fname);
  3215.                     MSG_OUTSTR("\"\n    to avoid this message.\n\n");
  3216.                     cmdline_row = msg_row;
  3217.                     --no_wait_return;
  3218.                     need_wait_return = TRUE;        /* call wait_return later */
  3219.                 }
  3220.             }
  3221.         }
  3222.  
  3223.         if (fname[n - 1] == 'a')    /* tried enough names, give up */
  3224.         {
  3225.             vim_free(fname);
  3226.             fname = NULL;
  3227.             break;
  3228.         }
  3229.         --fname[n - 1];                /* change last char of the name */
  3230.     }
  3231.  
  3232.     vim_free(dir_name);
  3233. #ifndef SHORT_FNAME
  3234.     if (dummyfd)        /* file has been created temporarily */
  3235.     {
  3236.         fclose(dummyfd);
  3237.         vim_remove(buf->b_xfilename);
  3238.     }
  3239. #endif
  3240.     return fname;
  3241. }
  3242.  
  3243.     static int
  3244. b0_magic_wrong(b0p)
  3245.     ZERO_BL *b0p;
  3246. {
  3247.     return (b0p->b0_magic_long != (long)B0_MAGIC_LONG ||
  3248.             b0p->b0_magic_int != (int)B0_MAGIC_INT ||
  3249.             b0p->b0_magic_short != (short)B0_MAGIC_SHORT ||
  3250.             b0p->b0_magic_char != B0_MAGIC_CHAR);
  3251. }
  3252.  
  3253. #ifdef CHECK_INODE
  3254. /*
  3255.  * Compare current file name with file name from swap file.
  3256.  * Try to use inode numbers when possible.
  3257.  * Return non-zero when files are different.
  3258.  *
  3259.  * When comparing file names a few things have to be taken into consideration:
  3260.  * - When working over a network the full path of a file depends on the host.
  3261.  *   We check the inode number if possible.  It is not 100% reliable though,
  3262.  *   because the device number cannot be used over a network.
  3263.  * - When a file does not exist yet (editing a new file) there is no inode
  3264.  *   number.
  3265.  * - The file name in a swap file may not be valid on the current host.  The
  3266.  *     "~user" form is used whenever possible to avoid this.
  3267.  *
  3268.  * This is getting complicated, let's make a table:
  3269.  *
  3270.  *                ino_c  ino_s  fname_c  fname_s  differ =
  3271.  *
  3272.  * both files exist -> compare inode numbers:
  3273.  *                != 0   != 0     X        X      ino_c != ino_s
  3274.  *
  3275.  * inode number(s) unknown, file names available -> compare file names
  3276.  *                == 0    X       OK       OK     fname_c != fname_s
  3277.  *                 X     == 0     OK       OK     fname_c != fname_s
  3278.  *
  3279.  * current file doesn't exist, file for swap file exist, file name(s) not
  3280.  * available -> probably different
  3281.  *                == 0   != 0    FAIL      X      TRUE
  3282.  *                == 0   != 0     X       FAIL    TRUE
  3283.  *
  3284.  * current file exists, inode for swap unknown, file name(s) not
  3285.  * available -> probably different
  3286.  *                != 0   == 0    FAIL      X      TRUE
  3287.  *                != 0   == 0     X       FAIL    TRUE
  3288.  *
  3289.  * current file doesn't exist, inode for swap unknown, one file name not
  3290.  * available -> probably different
  3291.  *                == 0   == 0    FAIL      OK     TRUE
  3292.  *                == 0   == 0     OK      FAIL    TRUE
  3293.  *
  3294.  * current file doesn't exist, inode for swap unknown, both file names not
  3295.  * available -> probably same file
  3296.  *                == 0   == 0    FAIL     FAIL    FALSE
  3297.  */
  3298.  
  3299.     static int
  3300. fnamecmp_ino(fname_c, fname_s, ino_block0)
  3301.     char_u        *fname_c;            /* current file name */
  3302.     char_u        *fname_s;            /* file name from swap file */
  3303.     long        ino_block0;
  3304. {
  3305.     struct stat    st;
  3306.     long        ino_c = 0;            /* ino of current file */
  3307.     long        ino_s;                /* ino of file from swap file */
  3308.     char_u        buf_c[MAXPATHL];    /* full path of fname_c */
  3309.     char_u        buf_s[MAXPATHL];    /* full path of fname_s */
  3310.     int            retval_c;            /* flag: buf_c valid */
  3311.     int            retval_s;            /* flag: buf_s valid */
  3312.  
  3313.  
  3314.     if (stat((char *)fname_c, &st) == 0)
  3315.         ino_c = st.st_ino;
  3316.  
  3317.     /*
  3318.      * First we try to get the inode from the file name, because the inode in
  3319.      * the swap file may be outdated.  If that fails (e.g. this path is not
  3320.      * valid on this machine), use the inode from block 0.
  3321.      */
  3322.     if (stat((char *)fname_s, &st) == 0)
  3323.         ino_s = st.st_ino;
  3324.     else
  3325.         ino_s = ino_block0;
  3326.  
  3327.     if (ino_c && ino_s)
  3328.         return (ino_c != ino_s);
  3329.  
  3330.     /*
  3331.      * One of the inode numbers is unknown, try a forced FullName() and
  3332.      * compare the file names.
  3333.      */
  3334.     retval_c = FullName(fname_c, buf_c, MAXPATHL, TRUE);
  3335.     retval_s = FullName(fname_s, buf_s, MAXPATHL, TRUE);
  3336.     if (retval_c == OK && retval_s == OK)
  3337.         return (STRCMP(buf_c, buf_s) != 0);
  3338.  
  3339.     /*
  3340.      * Can't compare inodes or filenames, guess that the files are different,
  3341.      * unless both appear not to exist at all.
  3342.      */
  3343.     if (ino_s == 0 && ino_c == 0 && retval_c == FAIL && retval_s == FAIL)
  3344.         return FALSE;
  3345.     return TRUE;
  3346. }
  3347. #endif /* CHECK_INODE */
  3348.  
  3349. /*
  3350.  * Move a long integer into a four byte character array.
  3351.  * Used for machine independency in block zero.
  3352.  */
  3353.     static void
  3354. long_to_char(n, s)
  3355.     long    n;
  3356.     char_u    *s;
  3357. {
  3358.     s[0] = (n & 0xff);
  3359.     n >>= 8;
  3360.     s[1] = (n & 0xff);
  3361.     n >>= 8;
  3362.     s[2] = (n & 0xff);
  3363.     n >>= 8;
  3364.     s[3] = (n & 0xff);
  3365. }
  3366.  
  3367.     static long
  3368. char_to_long(s)
  3369.     char_u    *s;
  3370. {
  3371.     long    retval;
  3372.  
  3373.     retval = s[3];
  3374.     retval <<= 8;
  3375.     retval += s[2];
  3376.     retval <<= 8;
  3377.     retval += s[1];
  3378.     retval <<= 8;
  3379.     retval += s[0];
  3380.  
  3381.     return retval;
  3382. }
  3383.